12

可能重复:
在 log4j 中,在记录之前检查 isDebugEnabled 是否会提高性能?

我见过人们以下列方式使用 log4j:

if(logger.isDebugEnabled())
{
    logger.debug(" message ");
}

但是,我检查了logger.debugAPI 的文档,发现它debug在记录消息之前检查是否已启用。在那种情况下,多写 if 有什么意义?

只写不就完全一样了吗

logger.debug(" message ");

?

4

6 回答 6

21

如果你真的只是在写作

logger.debug(" message ");

那么没有任何好处。但请考虑:

logger.debug("This: " + message + " happened on thread " + thread +
            "because " + cause);

如果结果将被丢弃,您不希望执行该字符串连接(以及可能更昂贵的转换 - 考虑您可能想要记录但转换为字符串的成本很高的事情)。

如果日志记录在正常情况下会对性能产生重大影响,那么添加日志记录代码将不利于您在突然想要打开诊断的情况下真正为您提供帮助。

于 2012-11-07T10:48:29.730 回答
7

我认为这里的想法是防止任何参数评估 - 在你的情况下它很简单,但例如让我们说它更像是:

logger.debug("Foo" + bar() + " bar: " + foo());

好的,这是人为的,但是如果未启用调试,您可能不想执行bar()foo()字符串连接......

于 2012-11-07T10:48:30.363 回答
2

一个原因可能是因为在构建消息时存在一些开销。例如:

if(debug.isDebugEnabled()) {
    String message = buildLogMessage()
    logger.debug(message);
}

如果buildLogMessage()运行需要一段时间,当您知道永远不会记录输出时,您可能不想运行它。

但是,解决此问题的更好方法是使用 an ObjectRender,以便仅在要记录该值时才完成到 String 的转换。

于 2012-11-07T10:50:35.287 回答
1

如果你花一点时间看看 log4j 的实现,你就会知道这是什么原因。当您编写时:logger.debug(" message ");log4j 附加程序始终附加 loggingEvent。这是昂贵的转换。if 条件是最好的,但在某些情况下很有用。

// AppenderAttachableImpl.class
public int appendLoopOnAppenders(LoggingEvent event) {
        int size = 0;
        if (appenderList != null) {
            size = appenderList.size();
            for (int i = 0; i < size; i++) {
                Appender appender = (Appender) appenderList.elementAt(i);
                appender.doAppend(event);
            }

        }
        return size;
    }
于 2012-11-07T10:57:29.377 回答
1

另一个原因是修改 HotSpot VM 的行为。不太确定它是如何工作的,但如果你在生产模式下运行(调试注销)——HotSpot VM 应该优化代码,就好像 if 语句和里面的所有东西都不存在一样。

于 2012-11-07T13:08:30.750 回答
0

在调用调试方法之前,可以执行可以通过条件句避免的代码,例如字符串连接。例子:

log.debug("Value of variable1:"+variable+" Value of variable2:"+variable2);

如果添加条件 if log.isDebugEnabled(),则不执行字符串连接。

这是唯一的好处。

于 2012-11-07T10:49:31.617 回答