可能重复:
In log4j, does checking isDebugEnabled before logging improve performance?
我见过以下方式使用log4j的人:
if(logger.isDebugEnabled())
{
logger.debug(" message ");
}
但是,我检查了logger.debug
API的文档,发现它在检查邮件之前检查是否启用了debug
。在那种情况下,写出额外的if是什么意思?
只是写
并不完全一样logger.debug(" message ");
答案 0 :(得分:21)
如果你真的只是写
logger.debug(" message ");
然后没有任何好处。但请考虑:
logger.debug("This: " + message + " happened on thread " + thread +
"because " + cause);
您不希望字符串连接(以及更昂贵的转换,可能 - 考虑您可能想要记录的内容,但转换为字符串的成本很高),如果结果就会被扔掉。
如果日志记录在正常情况下会对性能产生重大影响,那么添加日志记录代码就会受到阻碍,这些代码可能真正在突然想要启用诊断的情况下帮助您。
答案 1 :(得分:7)
我认为这里的想法是防止任何参数评估 - 在你的情况下它很简单,但是例如让我们说它更像是:
logger.debug("Foo" + bar() + " bar: " + foo());
好的,这是设计的,但如果未启用调试,您可能不想执行bar()
和foo()
以及字符串连接...
答案 2 :(得分:2)
一个原因可能是因为构建消息会产生一些开销。例如:
if(debug.isDebugEnabled()) {
String message = buildLogMessage()
logger.debug(message);
}
如果buildLogMessage()
需要一段时间才能运行,当您知道输出永远不会被记录时,您可能不想运行它。
但是,更好的解决方法是使用ObjectRender
,这样只有在记录值时才能转换为String。
答案 3 :(得分:1)
如果你花一点时间看看log4j的实现,你可以知道是什么原因。当你写:logger.debug(" message ");
log4j appender总是附加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;
}
答案 4 :(得分:1)
另一个原因是修改HotSpot VM的行为。不太确定它是如何工作的,但是如果你在生产模式下运行(调试注销) - HotSpot VM应该优化代码,好像if语句和里面的所有东西都没有。
答案 5 :(得分:0)
在调用调试方法之前,可以执行可以通过条件语句避免的代码,例如字符串连接。例如:
log.debug("Value of variable1:"+variable+" Value of variable2:"+variable2);
如果在log.isDebugEnabled()中添加条件,则不执行字符串连接。
这是唯一的好处。