使用...函数的Java日志记录器

6

Java日志允许使用以下语法:

m_logger.info("ID: {} NAME: {}", id, name);    // 1
m_logger.info("ID: " + id + " NAME: " + name); // 2

在第一种情况下,我们实际上是调用了...函数,因此每次都会创建一个新的Object[]。
我通过YourKit运行了一遍,看到了这个情况。
我的问题是,难道第一种情况不是一种昂贵的操作,我们应该一直避免使用吗?但我在很多代码中都看到了这种情况。使用#1有什么好处?
我想我们应该使用StringBuilder来获得最佳性能?
5个回答

5
m_logger.info("ID: {} NAME: {}", id, name);

这是惰性参数评估。如果关闭了INFO日志级别,则不会处理该字符串。实际上,构造一个new Object[n]并不是什么大问题,n通常(=正常情况下)是< 5
m_logger.info("ID: " + id + " NAME: " + name);

这个字符串每次都会被构造。


2
我的问题是,第一种情况不是一个昂贵的操作吗?我们应该尽可能避免使用它吗?
不是,特别是在程序执行的整个过程中。
使用#1我们得到了什么好处?
可读性,有时第一种方法更易于阅读为代码。生成的日志行相同。
我想我们应该使用StringBuilder来获得最佳性能吗?
不需要:https://dev59.com/JnI_5IYBdhLWcg3wFu_L#1532499

2
您关于在调用#1中创建一个新的Object[]数组是正确的。但是,在#2中创建了一个新的StringBuilder对象*,然后对idname都调用了toString()(这可能是一个String,但这不是重点)。
虽然在#1中m_logger.info内部发生类似的格式化,但这取决于日志记录器的设置,它可能会执行或不执行该操作。
因此,就性能而言,需要比较创建Object[]加上由设置驱动的可选格式化与调用内部的急切格式化。由于不能假设所有级别始终处于格式化状态,并且因为创建Object[]相对廉价,所以通常情况下更喜欢使用#1。 * 您不需要显式创建StringBuilder,编译器会为您执行此操作。有关Java如何在内部处理字符串连接的答案,请参见此Q&A

2
这个决定背后有几个隐藏的原因。
  1. Argument evaluation.

    In first case string will not be interpolated (i.e. calculated) if info logging level is not enabled (for example only ERROR is enabled). In your second case this string will be calculated every time your program reaches this statement, which may lead to unexpected performance impacts caused by logging. As noted correctly above adding StringBuilder will not help you as compiler will do it for you.

  2. Execution flow. Look into source code of logger (log4j 2.7)

    @Override
    public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final String message,
        final Object p0, final Object p1) {
        if (isEnabled(level, marker, message, p0, p1)) {
          logMessage(fqcn, level, marker, message, p0, p1);
      }
    }
    

    It checks in if clause that corresponding mode is enabled. Once Java will evaluate this flow once it will become faster utilizing branch prediction optimization.


0

据我所知,这是从用户角度出发的。

  • 一些开发人员可能会采用情况#1。
  • 一些开发人员可能会采用情况#2。

这是Java的一个主要特征。在许多方面都是如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接