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

选项1:

logger.debug("some debug text");

但是一些链接建议最好先检查isDebugEnabled(),比如:

选项2:

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

所以我的问题是“选项2是否能提高性能?”

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

如果将值分配给debugEnabled变量,和 实际上由logger.debug()方法调用。

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


当前回答

Since in option 1 the message string is a constant, there is absolutely no gain in wrapping the logging statement with a condition, on the contrary, if the log statement is debug enabled, you will be evaluating twice, once in the isDebugEnabled() method and once in debug() method. The cost of invoking isDebugEnabled() is in the order of 5 to 30 nanoseconds which should be negligible for most practical purposes. Thus, option 2 is not desirable because it pollutes your code and provides no other gain.

其他回答

比如@erickson,这要看情况。如果我没记错的话,isDebugEnabled已经在Log4j的debug()方法中构建了。 在我看来,只要你不在调试语句中做一些昂贵的计算,比如在对象上循环,执行计算和连接字符串,你就可以了。

StringBuilder buffer = new StringBuilder();
for(Object o : myHugeCollection){
  buffer.append(o.getName()).append(":");
  buffer.append(o.getResultFromExpensiveComputation()).append(",");
}
log.debug(buffer.toString());

会更好

if (log.isDebugEnabled(){
  StringBuilder buffer = new StringBuilder();
  for(Object o : myHugeCollection){
    buffer.append(o.getName()).append(":");
    buffer.append(o.getResultFromExpensiveComputation()).append(",");
  }
  log.debug(buffer.toString());
}

我建议大多数人使用选项2,因为它不是特别贵。

案例1: log.debug(一个字符串)

例2: Log.debug(“一个字符串”+“两个字符串”+对象。toString + object2.toString)

在调用这两个函数时,必须计算log.debug中的参数字符串(无论是CASE 1还是Case2)。这就是人们所说的“昂贵”。如果你在它之前有一个条件,'isDebugEnabled()',这些不需要计算,这是性能保存的地方。

截至2。x, Apache Log4j内置了这个检查,所以不再需要isDebugEnabled()。只需执行debug(),如果未启用消息,则消息将被抑制。

由于许多人在搜索log4j2时可能会看到这个答案,而且几乎所有当前的答案都不考虑log4j2或它最近的变化,因此这应该能够回答这个问题。

log4j2支持供应商(目前是它们自己的实现,但根据文档,计划在3.0版本中使用Java的供应商接口)。你可以在手册里读到更多。这允许你把昂贵的日志消息创建到一个供应商,它只创建消息,如果它将被记录:

LogManager.getLogger().debug(() -> createExpensiveLogMessage());

Since in option 1 the message string is a constant, there is absolutely no gain in wrapping the logging statement with a condition, on the contrary, if the log statement is debug enabled, you will be evaluating twice, once in the isDebugEnabled() method and once in debug() method. The cost of invoking isDebugEnabled() is in the order of 5 to 30 nanoseconds which should be negligible for most practical purposes. Thus, option 2 is not desirable because it pollutes your code and provides no other gain.