Performance: Faster method caller lookup
Col-E opened this issue · comments
For a performance improvement you can replace Thread.currentThread().getStackTrace()
with new Exception().getStackTrace()
Additional context
The Thread#getStackTrace()
approach is slower because it has to be thread-safe. More details on performance are in the comments.
Thank you for the suggestion! I didn't know about this.
The bug report at the page of java mentions this is resolved from java 6 onwards and this library works from java 8 onwards, so is the alternative still valid?
I have run a test with a loop of n=1.000.000
- with getting the stack-trace from
a new Exception
has a total time of52.085 ms
- with getting the stack-trace from
Thread.currentThread()
has a total time of52.038 ms
The results are similar, but maybe I am doing something wrong?
Ah it is indeed largely fixed in Java 8. I overlooked that.
// Thread.java
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// optimization so we do not call into the vm for threads that
// have not yet started or have terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
StackTraceElement[] stackTrace = stackTraceArray[0];
// a thread that was alive during the previous isAlive call may have
// since terminated, therefore not having a stacktrace.
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// Don't need JVM help for current thread
return (new Exception()).getStackTrace();
}
}
In the use case of GateKeeper the extra work done here is the call to public static native Thread currentThread()
and the redundant call to Thread.currentThread()
inside the method shown above to check vs the current instance.
Swapping to new Exception()
will remove this minor redundancy but its a minor improvement.
Thank you for the detailed explanation and investigation! I like the alternative as it would not need to do the additional checks under the covers as you mentioned. I will switch to new Exception()
for getting the stacktrace. See here for the related commit: c636100