feat: add performance debug logging (wip)
diff --git a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
index 1ecd7f7..c0a7b9d 100644
--- a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
+++ b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
@@ -203,6 +203,7 @@
}
private static final Logger log = LoggerFactory.getLogger(ModelAdapterFactory.class);
+ private static final Logger perfLog = LoggerFactory.getLogger(ModelAdapterFactory.class.getName() + "-perf");
private final ConcurrentMap<String, RankedServices<Injector>> injectors = new ConcurrentHashMap<>();
private final RankedServices<Injector> sortedInjectors = new RankedServices<>();
@@ -249,7 +250,7 @@
@Override
@SuppressWarnings("null")
public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
- Result<AdapterType> result = internalCreateModel(adaptable, type);
+ Result<AdapterType> result = internalCreateModelMeasured(adaptable, type);
if (!result.wasSuccessful()) {
if (result == Result.POST_CONSTRUCT_PREVENTED_MODEL_CONSTRUCTION) {
log.debug("Could not adapt to model as PostConstruct method returned false"); // do no construct runtime exception in this case
@@ -265,7 +266,7 @@
@Override
public @NotNull <ModelType> ModelType createModel(@NotNull Object adaptable, @NotNull Class<ModelType> type) throws MissingElementsException,
InvalidAdaptableException, ValidationException, InvalidModelException {
- Result<ModelType> result = internalCreateModel(adaptable, type);
+ Result<ModelType> result = internalCreateModelMeasured(adaptable, type);
if (!result.wasSuccessful()) {
throw result.getThrowable();
}
@@ -348,6 +349,31 @@
return adaptableCache;
}
+
+ private <ModelType> Result<ModelType> internalCreateModelMeasured(@NotNull Object adaptable, @NotNull Class<ModelType> type) {
+ Result<ModelType> result;
+ if (perfLog.isDebugEnabled()) {
+ long startTime = perfLog.isDebugEnabled() ? System.nanoTime() : -1;
+ ThreadInvocationCounter threadInvocationCounter = invocationCountThreadLocal.get();
+ threadInvocationCounter.resetStats();
+
+ result = internalCreateModel(adaptable, type);
+
+ double duration = ((double) System.nanoTime() - startTime) / 1000000.0;
+
+ perfLog.debug("createdModel({},{}) took {}ms, instantiations {}, max recursion {}",
+ adaptable.getClass().getName(),
+ type.getName(),
+ duration,
+ threadInvocationCounter.getOverallCount(),
+ threadInvocationCounter.getMaxRecursion());
+ } else {
+ result = internalCreateModel(adaptable, type);
+ }
+
+ return result;
+ }
+
@SuppressWarnings("unchecked")
<ModelType> Result<ModelType> internalCreateModel(final Object adaptable, final Class<ModelType> requestedType) {
Result<ModelType> result;
@@ -1304,7 +1330,7 @@
if (clazz == null) {
throw new ModelClassException("Could find model registered for resource type: " + resource.getResourceType());
}
- return handleBoundModelResult(internalCreateModel(resource, clazz));
+ return handleBoundModelResult(internalCreateModelMeasured(resource, clazz));
}
@Override
@@ -1313,7 +1339,7 @@
if (clazz == null) {
throw new ModelClassException("Could find model registered for request path: " + request.getServletPath());
}
- return handleBoundModelResult(internalCreateModel(request, clazz));
+ return handleBoundModelResult(internalCreateModelMeasured(request, clazz));
}
private Object handleBoundModelResult(Result<?> result) {
@@ -1344,7 +1370,7 @@
if (clazz == null) {
throw new ModelClassException("Could find model registered for resource type: " + resource.getResourceType());
}
- Result<?> result = internalCreateModel(resource, clazz);
+ Result<?> result = internalCreateModelMeasured(resource, clazz);
return handleAndExportResult(result, name, targetClass, options);
}
@@ -1355,7 +1381,7 @@
if (clazz == null) {
throw new ModelClassException("Could find model registered for request path: " + request.getServletPath());
}
- Result<?> result = internalCreateModel(request, clazz);
+ Result<?> result = internalCreateModelMeasured(request, clazz);
return handleAndExportResult(result, name, targetClass, options);
}
diff --git a/src/main/java/org/apache/sling/models/impl/ThreadInvocationCounter.java b/src/main/java/org/apache/sling/models/impl/ThreadInvocationCounter.java
index b386aa5..e1c454e 100644
--- a/src/main/java/org/apache/sling/models/impl/ThreadInvocationCounter.java
+++ b/src/main/java/org/apache/sling/models/impl/ThreadInvocationCounter.java
@@ -21,6 +21,8 @@
class ThreadInvocationCounter {
private int count;
+ private int max;
+ private int overallCount;
final int maxRecursionDepth;
@@ -28,12 +30,29 @@
this.maxRecursionDepth = maxRecursionDepth;
}
+ public void resetStats() {
+ max = 0;
+ overallCount = 0;
+ }
+
+ public int getMaxRecursion() {
+ return max;
+ }
+
+ public int getOverallCount() {
+ return overallCount;
+ }
+
public boolean isMaximumReached() {
return count >= maxRecursionDepth;
}
public void increase() {
this.count++;
+ this.overallCount++;
+ if (count > max) {
+ max = count;
+ }
}
public void decrease() {