-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Fix extended stack trace (i.e., %xEx
) rendering performance regression
#3123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@ppkarwasz @vy ![]() ![]() Will continue to check for improvement |
log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ClassResourceInfo.java
Outdated
Show resolved
Hide resolved
...src/main/java/org/apache/logging/log4j/core/pattern/ThrowableExtendedStackTraceRenderer.java
Outdated
Show resolved
Hide resolved
My benchmark shows that these changes are ~10% slower than 2.24.1, and use 3x the heap. That is far better than previous 2.25.0, which was more than 2x slower and used ~15x the heap. What level of performance regression is acceptable? |
They seem more than acceptable to me. These are figures using synchronous logging, right? They seem more than acceptable to me. For asynchronous loggers, the performance regression is probably higher, since the Regardless of the results of asynchronous loggers, I think that the throwable chapter of
If users complain about the asynchronous performance of |
%xEx
) rendering performance regression
I am still observing a ~10x performance regression. I use the following crude script: import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
import org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter;
import java.net.Socket;
public class Log4j2Issue3123 {
public static void main(String[] args) {
final Exception error = createException();
final LogEvent logEvent = Log4jLogEvent.newBuilder().setThrown(error).build();
final ExtendedThrowablePatternConverter converter = ExtendedThrowablePatternConverter.newInstance(null, null);
long startInstantNanos = System.nanoTime();
final StringBuilder buffer = new StringBuilder();
for (int i = 0; i < 5_000_000; i++) {
buffer.setLength(0);
converter.format(logEvent, buffer);
}
double durationSeconds = (System.nanoTime() - startInstantNanos) / 1e9;
System.out.format("took %.3f s%n", durationSeconds);
// 2.24.1 - 1.753 s
// 2.25.0 - 11.281 s
}
private static Exception createException() {
try {
new Socket("localhost", -1);
throw new IllegalStateException("should not have reached here");
} catch (final Exception error) {
return error;
}
}
} |
@jengebr, mind sharing the details about your benchmark, please? |
Sure - my benchmark is attached. Be sure to use I vary the scenario by changing the classpath to include the desired log4j version. |
@vy I confirm your results; profiling shows your script is bottlenecked on the |
@vy @jengebr ![]() |
And I noticed that compare to ![]() ![]() |
I found that current way to load class wastes 4GB more memory, compare to old approach(simple if-else way) according to the profiler. I guess it's the overhead of Stream API. |
Also the current way of using |
Awesome findings @alan0428a! 🤩 |
@alan0428a, what do you mean by this? What would be your suggestion instead? |
I can confirm that with the
@ppkarwasz, agreed. I will implement the changes you suggested. |
2.25.0-SNAPSHOT
#3106, due to Disruptor + many logger.error("aa", new Exception("aaa")),stuck on Th… #3093.%xEx
to%ex