在 log4j 中,在日志记录之前检查 isDebugEnabled 是否会提高性能?

2022-08-31 05:44:42

我正在使用Log4J在我的应用程序中进行日志记录。以前我使用调试调用,如:

选项 1:

logger.debug("some debug text");

但有些链接建议最好先检查一下,例如:isDebugEnabled()

选项 2:

boolean debugEnabled = logger.isDebugEnabled();
if (debugEnabled) {
    logger.debug("some debug text");
}

所以我的问题是“选项2是否以任何方式提高了性能?

因为在任何情况下,Log4J框架对调试启用都有相同的检查。对于选项2,如果我们在单个方法或类中使用多个调试语句,则可能是有益的,其中框架不需要多次调用方法(在每次调用时);在这种情况下,它只调用方法一次,如果Log4J配置为调试级别,那么实际上它调用方法两次:isDebugEnabled()isDebugEnabled()isDebugEnabled()

  1. 如果为调试赋值启用变量,并且
  2. 实际上由 logger.debug() 方法调用。

我不认为如果我们在方法或类中编写多个语句并根据选项1调用方法,那么与选项2相比,Log4J框架的开销是。由于是一种非常小的方法(就代码而言),因此它可能是内联的良好候选者。logger.debug()debug()isDebugEnabled()


答案 1

在这种特殊情况下,备选方案1更好。

保护语句(检查)是为了防止在涉及调用各种对象的方法并连接结果时对日志消息进行潜在的昂贵计算。isDebugEnabled()toString()

在给定的示例中,日志消息是一个常量字符串,因此让记录器丢弃它与检查记录器是否已启用一样有效,并且由于分支较少,因此降低了代码的复杂性。

更好的做法是使用更新的日志记录框架,其中日志语句采用格式规范和参数列表,以供记录器替换 , 但只有在启用记录器时才“懒惰”。这是 slf4j 采用的方法。

有关详细信息,请参阅我对相关问题的回答,以及使用 log4j 执行此类操作的示例。


答案 2

由于在选项 1 中消息字符串是一个常量,因此将日志记录语句包装为条件绝对没有好处,相反,如果启用了 debug 语句,则将计算两次,一次在方法中,一次在方法中。调用的成本约为5至30纳秒,对于大多数实际目的来说,这应该可以忽略不计。因此,选项 2 是不可取的,因为它会污染您的代码,并且不会提供其他收益。isDebugEnabled()debug()isDebugEnabled()


推荐