Java 如何评估记录器的性能?

Java 如何评估记录器的性能?,java,performance,logging,Java,Performance,Logging,我正在做一个关于在Java框架中改进日志(特别是log4j)性能的项目。现在我有两个记录器从一个源读取并将相同的日志信息转储到两个不同的文件中,我可以通过从一个具有有限行数的文件读取或从源生成器读取来控制源,该生成器一直在生成信息(无限行数) 现在,我想评估两个记录器的性能,即如果要记录的信息相同,哪一个更快。你对怎么做有什么想法吗? PS我想我需要一个线程来计算文件的行数,但我不确定如何计算。 非常感谢您的帮助。Log4J不仅是开源开发中的当前标准。它自称是快速灵活的:速度第一,灵活性第二。但

我正在做一个关于在Java框架中改进日志(特别是log4j)性能的项目。现在我有两个记录器从一个源读取并将相同的日志信息转储到两个不同的文件中,我可以通过从一个具有有限行数的文件读取或从源生成器读取来控制源,该生成器一直在生成信息(无限行数)

现在,我想评估两个记录器的性能,即如果要记录的信息相同,哪一个更快。你对怎么做有什么想法吗? PS我想我需要一个线程来计算文件的行数,但我不确定如何计算。
非常感谢您的帮助。

Log4J不仅是开源开发中的当前标准。它自称是快速灵活的:速度第一,灵活性第二。但在关键时刻也有一些陷阱

日志请求的成本包括方法调用和整数比较。这通常是每次通话约1-20纳秒(取决于您的处理器)。但是,这不包括参数构建的“隐藏”成本

一个简单的例子:

logger.debug("Value: " + x*y);
无论消息是否实际被记录,参数构造都将导致额外的成本。参数构造的这些成本可能相当高,并且取决于所涉及参数的大小

为避免参数施工成本:

if(logger.isDebugEnabled() {
  logger.debug("Value: " + x*y);
}
如果禁用调试,则不会产生参数构造成本。另一方面,如果记录器启用了调试,则评估记录器是否启用的成本将增加两倍:一次在调试启用中,一次在调试中。这是一个微不足道的开销,因为评估记录器需要实际记录所需时间的1%左右

因此,如果速度是一个真正的问题,您应该仔细检查您的日志记录语句,以确定“隐藏”成本


参考资料:

真正重要的问题是:

  • 您正在登录到哪些设备?(最重要)

  • 日志记录是在当前线程中执行还是在后台线程中执行

  • 格式模式相同吗

  • 未记录的消息未创建。e、 它不会生成消息,不会打印

  • 您是使用字符串生成消息还是使用较低级别的文本生成?(只有在其余的都是最优的情况下才重要)

如果在每种情况下打印相同数量的行,则计数的重要性低于所花费的总时间


这里有一个简单的测试

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);
待办事项窗口打印

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

这是所有伐木工人的典型情况,设备是最关键的因素。

我不得不在工作中解决这个问题;我编写了一个SLF4J的实现,并用Log4J对其进行了测试。我创建了一个线束,它将通过记录器在固定数量的线程(t)上泵送固定数量的消息(n)。我在几个试验中测试了(n,t)的各种组合的执行时间,并检查了聚合结果的中值、平均值和p90值。我还将应用程序中SLF4J的实现在Log4J和我的实现之间交换,并通过预先存在的性能测试运行应用程序,以查看其对应用程序的影响

我的忠告是:

  • 在模拟应用程序的测试线束中练习每个记录器
  • 如果可行,请在模拟负载(即使用重播或生成的数据)下练习应用程序中的每个记录器
    您是否对典型日志消息的日志记录时间进行了计时?你有什么可以分享的实际基准吗?谢谢,我以前试过,但我的问题是如何评估这两个记录器,而不是如何使其更快。不管怎样,谢谢你的回复。不完全是,这是我的实习项目。嗨,彼得,你是对的,在不同的设备上写东西会导致明显不同的时间。现在,我考虑两个日志程序(可能具有相同的接口,但不同的实现会导致性能差异)都在写入(不同的)文件,并且这些日志在一个框架中运行,而不是在main()方法中运行,我无法使用System.nanoTime()方法记录日志之前的时间,然后在日志之后获取另一个时间。这些文件一直都是从不同的组件追加的。我所能做的就是编写另一个线程来访问这些文件,我的问题是,考虑到上面的场景,我如何比较哪个记录器更快?对不起,我的解释太多了。你可以试着运行相同的测试。;)感谢Paul事实上我最近一直在这样做,我发现评估性能最简单、最准确的方法是在log4j appender中打开%r。关于您自己的slf4j实现,它比log4j快吗?log4j是否存在可以改进的大缺点?我也在做一个项目来提高log4j的性能,也许我们可以讨论更多:)
    Average log time was 1,002 ns