Log4J2 同步记录器比混合 async/sync 记录器更快
Log4J2 sync loggers faster than mixed async/sync loggers
基于https://logging.apache.org/log4j/2.x/manual/async.html,我想使用混合同步和异步记录器方法,以便从所有同步记录器的性能改进中获益。
基准代码:
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.");
}
Log4j2 配置与文档中的完全一致 (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>
通过混合 sync/async 记录器配置,我得到了 33,400 logs/sec.
现在,如果我将 AsyncLogger "com.foo.Bar" 替换为常规 Logger,我将获得 35,300 logs/sec.
为什么同步记录器策略更快,根据图表它应该有更高的吞吐量?
在按照他们的建议进行基准测试之前,我已经尝试了各种其他方法,例如 "warming up" JVM,但没有帮助。
请注意,如果我将 属性 Log4jContextSelector 设置为 "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector" 以激活 "all async" 记录器,我将得到大约 86,400 logs/seconds。不幸的是,由于其他原因我无法使用该选项。
使用 log4j2-2.3、disruptor-3.3.2。
OS 是 Ubuntu,8 核。
在开始测量之前,我建议您记录较少数量的消息,比如 100,000 条左右,然后在开始测量循环之前休眠一秒钟。 (您不想在这里测量 log4j 的初始化或 JVM 优化。)
如果在日志记录循环结束之前(在尝试停止 appender 之前)进行测量,性能结果如何?
也可以尝试在您的配置中设置 includeLocation="false"。这应该有很大的不同。
我认为您不应该手动停止附加程序(请参阅我对您其他问题的回答)。
基于https://logging.apache.org/log4j/2.x/manual/async.html,我想使用混合同步和异步记录器方法,以便从所有同步记录器的性能改进中获益。
基准代码:
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.");
}
Log4j2 配置与文档中的完全一致 (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>
通过混合 sync/async 记录器配置,我得到了 33,400 logs/sec.
现在,如果我将 AsyncLogger "com.foo.Bar" 替换为常规 Logger,我将获得 35,300 logs/sec.
为什么同步记录器策略更快,根据图表它应该有更高的吞吐量?
在按照他们的建议进行基准测试之前,我已经尝试了各种其他方法,例如 "warming up" JVM,但没有帮助。
请注意,如果我将 属性 Log4jContextSelector 设置为 "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector" 以激活 "all async" 记录器,我将得到大约 86,400 logs/seconds。不幸的是,由于其他原因我无法使用该选项。
使用 log4j2-2.3、disruptor-3.3.2。
OS 是 Ubuntu,8 核。
在开始测量之前,我建议您记录较少数量的消息,比如 100,000 条左右,然后在开始测量循环之前休眠一秒钟。 (您不想在这里测量 log4j 的初始化或 JVM 优化。)
如果在日志记录循环结束之前(在尝试停止 appender 之前)进行测量,性能结果如何?
也可以尝试在您的配置中设置 includeLocation="false"。这应该有很大的不同。
我认为您不应该手动停止附加程序(请参阅我对您其他问题的回答)。