我正在做一个关于在Java框架中提高日志性能(特别是log4j)的项目。现在我有两个记录器从源读取并将相同的记录信息转储到两个不同的文件,我可以通过读取具有有限行数的文件或从源生成器读取来控制源,这将继续生成信息所有的时间(无限多行)。
现在我想评估两个记录器的性能,即在记录相同信息的情况下哪一个更快。你对这个怎么做有什么想法吗? PS我以为我需要一个线程来计算文件的行数,但我不确定如何。 非常感谢任何帮助。
答案 0 :(得分:5)
Log4J不仅是开源开发的当前标准。它声称快速而灵活:速度第一,灵活性第二。但是,在危机问题上存在一些陷阱。
日志请求的成本包括方法调用和整数比较。每次通话通常约为1-20ns(取决于您的处理器)。但是,这不包括参数构造的“隐藏”成本。
一个简单的例子:
logger.debug("Value: " + x*y);
无论是否实际记录消息,参数构造都会产生额外成本。参数构造的这些成本可能非常高,并且取决于所涉及参数的大小。
避免参数构建成本:
if(logger.isDebugEnabled() {
logger.debug("Value: " + x*y);
}
如果禁用调试,这不会产生参数构造的成本。另一方面,如果记录器是启用调试的,则会产生两倍于评估记录器是否启用的成本:一次在debugEnabled中,一次在调试中。这是一个微不足道的开销,因为评估记录器需要大约1%的实际记录时间。
因此,如果速度是一个真正的问题,您应该仔细检查您的日志记录语句中的“隐藏”费用。
答案 1 :(得分:2)
唯一真正重要的问题是:
您要登录哪些设备? (最重要的)
是在当前线程还是后台线程中执行日志记录?
格式模式是否相同?
是否未创建未记录的消息。例如它不构建不会打印的消息。
您使用字符串构建邮件还是较低级别的文本构建? (只有在其余部分最佳时才重要)
如果在每种情况下打印相同数量的行,则计数不会比总时间重要。
这是一个简单的测试
Logger log = Logger.getAnonymousLogger();
int runs = 100 * 1000;
long start = System.nanoTime();
for(int i=0;i< runs;i++)
log.info("Hello World! "+i);
long time = System.nanoTime() - start;
System.out.printf("Average log time was %,d ns%n", time/runs);
到IDE GUI打印
Average log time was 109,270 ns
到DOS窗口打印
Average log time was 354,015 ns
仅写入文件
Handler handler = new FileHandler("test.log", 1024 * 1024, 10);
Logger log = Logger.getAnonymousLogger();
log.setUseParentHandlers(false);
log.addHandler(handler);
打印
Average log time was 29,688 ns
没有设备
Average log time was 1,002 ns
这是所有记录仪的典型情况,设备是最关键的因素。
答案 2 :(得分:0)
我必须在工作中解决这个问题;我写了一个SLF4J的实现,并正在对Log4J进行测试。我创建了一个线束,可以在固定数量的线程(t)上通过记录器抽取固定数量的消息(n)。我在几个试验中测试了(n,t)的各种组合的测量执行时间,并检查了聚合结果的中值,平均值和p90值。我还在我们的应用程序中在Log4J和我的实现之间交换了SLF4J的实现,并通过预先存在的性能测试来运行应用程序,以查看我们的应用程序中的影响。
我的建议: