【问题标题】:log.info using log.isInfoEnabled使用 log.isInfoEnabled 的 log.info
【发布时间】:2012-01-09 12:00:19
【问题描述】:

我们正在使用 SLF4J

基于团队最近的讨论

if(LOG.isDebugEnabled()){
  LOG.debug("hello " + a + " world" + b);
}

优于

LOG.debug("hello {} world {}", a, b);

因为在后一种情况下,即使未启用“调试”,也会创建字符串hello {} world {}。换句话说,我们总是在创建字符串,即使它不是必需的。

我喜欢后一个版本,因为它显着提高了可读性。

有人可以提供意见吗?

问候,

沙杜尔。

编辑

让我换一种说法。

哪种方法更好或哪种方法被最广泛接受?

沙杜尔。

【问题讨论】:

    标签: java logging slf4j


    【解决方案1】:

    不,较短的版本不会创建hello {} world {}”字符串。在编译和类加载期间,该字符串已创建并放置在常量池中。你总是从常量池中引用同一个实例,它和引用常量int 一样便宜。

    但字符串 是在第一种形式中创建的,因为您使用的是字符串连接。

    唯一的额外开销是使用三个参数调用LOG.debug,这在内部调用isDebugEnabled() 时什么都不做。它也有可能被内联。

    话虽如此,我会在 99% 的情况下选择更短的形式。我会显式调用isDebugEnabled 的唯一情况是计算要记录的消息的成本很高:

    if(LOG.isDebugEnabled()){
      LOG.debug("hello {} world {}", cheap, veryExpensive());
    }
    

    如果veryExpensive() 是,ekhem,非常昂贵,那么明智的做法是避免调用它,如果它会被丢弃。 BTW veryExpensive() 不应该有任何 side effects 并且很难想象长时间运行、无副作用的方法...

    【讨论】:

    • 如果你有一个“veryExpensive()”,然后创建一个匿名对象,其中调用veryExpensive() 的toString() 并传递它。
    • @ThorbjørnRavnAndersen:不错的技巧,但是恕我直言有点晦涩难懂。在slf4s(SLF4J 的Scala 包装器)中,您可以安全地调用:LOG.debug("hello " + veryExpensive()); - 因为debug() 参数是一个返回String 而不是String 本身的函数。该函数仅在日志级别足够时调用。所以它与您的解决方案非常相似 - 传递一段代码。很整洁!
    【解决方案2】:

    创建String 对性能的影响可以忽略不计。但是由于SLF4J documentation指定"...这种形式不会产生参数构造的成本,以防日志语句被禁用 " 意味着字符串甚至没有被创建。

    经过一番考虑,“人力开销”,即代码清晰的重要性使我们决定支持第二个示例。 更重要的是,调用(以及写入和读取)isXEnabled 方法也会产生开销。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多