Based on https://logging.apache.org/log4j/2.x/manual/async.html I want to use the Mixing Synchronous and Asynchronous Loggers approach in order to benefit from some performance improvement over the all synchronous loggers.
The benchmark code:
public static void main(String[] args) {
org.apache.logging.log4j.Logger log4j2Logger = org.apache.logging.log4j.LogManager
.getLogger("com.foo.Bar");
long start = System.currentTimeMillis();
int nbLogMessages = 1 * 1000 * 1000;
for (int i = 0; i < nbLogMessages; i++) {
log4j2Logger.info("Log Message");
}
org.apache.logging.log4j.core.Logger coreLogger = (org.apache.logging.log4j.core.Logger) log4j2Logger;
org.apache.logging.log4j.core.LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) coreLogger
.getContext();
Map<String, org.apache.logging.log4j.core.Appender> appenders = context
.getConfiguration().getAppenders();
for (org.apache.logging.log4j.core.Appender appender : appenders
.values()) {
appender.stop();
}
long elapsed = System.currentTimeMillis() - start;
System.out.println("Elapsed " + elapsed + "ms "
+ (nbLogMessages * 1000 / elapsed) + "logs/sec.");
}
The Log4j2 configuration is exactly the one in the doc (https://logging.apache.org/log4j/2.x/manual/async.html):
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<RandomAccessFile name="RandomAccessFile" fileName="/tmp/asyncWithLocation.log" immediateFlush="false" append="false">
<PatternLayout>
<Pattern>%d %p %class{1.} [%t] %location %m %ex%n</Pattern>
</PatternLayout>
</RandomAccessFile>
</Appenders>
<Loggers>
<!-- pattern layout actually uses location, so we need to include it -->
<AsyncLogger name="com.foo.Bar" level="trace" includeLocation="true">
<AppenderRef ref="RandomAccessFile"/>
</AsyncLogger>
<Root level="info" includeLocation="true">
<AppenderRef ref="RandomAccessFile"/>
</Root>
</Loggers>
</Configuration>
With that mixed sync/async logger config I get around 33,400 logs/sec.
Now if I replace the AsyncLogger "com.foo.Bar" with a regular Logger I get around 35,300 logs/sec.
How come the synchronous logger strategy is faster, according to the graphs it should have a way higher throughput no?
I've tried various other things like "warming up" the JVM before doing the benchmark like they recommend but it didn't help.
Note that if I set the property Log4jContextSelector to "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector" to activate the "all async" loggers, I get around 86,400 logs/seconds. Unfortunately I can't use that option for other reasons.
Using log4j2-2.3, disruptor-3.3.2.
OS is Ubuntu, 8 cores.