陷阱 - 创建日志消息的开销

TRACEDEBUG 日志级别可以在运行时传达给定代码操作的高细节。通常建议将日志级别设置在这些以上,但是必须注意这些语句即使在看似关闭时也不会影响性能。

考虑这个日志语句:

// Processing a request of some kind, logging the parameters
LOG.debug("Request coming from " + myInetAddress.toString() 
          + " parameters: " + Arrays.toString(veryLongParamArray));

即使将日志级别设置为 INFO,也会在每次执行该行时评估传递给 debug() 的参数。这使得它在几个方面不必要地消耗:

  • String 连接:将创建多个 String 实例
  • InetAddress 甚至可以进行 DNS 查找。
  • veryLongParamArray 可能会很长 - 从中​​创建一个 String 消耗内存,需要时间

大多数日志记录框架提供了使用修复字符串和对象引用来创建日志消息仅在实际记录消息时才会评估日志消息。例:

// No toString() evaluation, no string concatenation if debug is disabled
LOG.debug("Request coming from {} parameters: {}", myInetAddress, parameters));

只要可以使用 String.valueOf(Object) 将所有参数转换为字符串,这都可以很好地工作。如果日志消息计算更复杂,则可以在记录之前检查日志级别:

if (LOG.isDebugEnabled()) {
    // Argument expression evaluated only when DEBUG is enabled
    LOG.debug("Request coming from {}, parameters: {}", myInetAddress,
              Arrays.toString(veryLongParamArray);
}

这里,仅当 DEBUG 实际启用时,才会处理具有昂贵的 Arrays.toString(Obect[]) 计算的 LOG.debug()