在这里辩论帮助我.. :)
这里的slf4j站点http://www.slf4j.org/faq.html#logging_performance表示由于参数化日志记录,不需要日志记录保护。即而不是写作:
if(logger.isDebugEnabled()) {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
你可以逃脱:
Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);
这是否真的没问题,或者是否会产生(虽然更低)创建传递给trace方法的静态字符串的成本..?
答案 0 :(得分:45)
我会尝试从另一个角度来看待我的两分钱
参数化日志记录的好处是什么?
您只需推迟 toString()
调用和字符串连接,直到确实需要为止,这时您必须记录消息。这将在禁用特定日志记录操作时优化性能。如果不确定,请检查source code for SLF4J。
参数化日志记录是否会使警卫在所有情况下都无用?
没有。
在哪些情况下,伐木卫兵会被使用?
当还有其他潜在的昂贵操作时。
例如(如果禁用此特定日志记录操作),如果我们没有日志记录保护
logger.debug("User name: {}", getUserService().getCurrentUser());
obj = getUserService().getCurrentUser()
"User name: " + obj.toString()
如果我们使用日志记录保护:
if (logger.isDebugEnabled()) {
logger.debug("User: {}", getUserService().getCurrentUser());
}
logger.isDebugEnabled()
obj = getUserService().getCurrentUser()
"User name: " + obj.toString()
在后一种情况下,当启用此特定日志记录操作时,我们会以检查isDebugEnabled()
两次为代价来节省成本。
注意:这只是一个例子,而不是在这里讨论好/坏做法。
答案 1 :(得分:17)
编写和阅读所有这些if(logger.isDebugEnabled()) {}
可能会花费他们为您节省的时间。
当然,调用log方法并不是免费的,但调用isDebugEnabled()
也是如此。因此,如果使用此模式,则为每个活动的日志语句支付更多费用(因为日志记录框架将检查级别两次)。
它也使代码混乱。
在实践中,我没有发现性能损失足以打扰。
如果日志记录对您来说太慢,请编写一个非阻塞appender,将日志事件推送到队列中,而不需要几次检查,并使用后台线程来处理它们。
背景:标准的appender都是同步的,因此登录多线程应用程序会导致许多小的暂停,所有线程都会等待将日志消息写入文件。
答案 2 :(得分:8)
由于字符串创建,未使用防护。
相反,它通常用于避免可能昂贵的参数表达式,如entry[i].retrieveExtendedDebugInformation().formatNicely()
。为此,logback确保仅在实际打印日志消息时评估参数,而log4j在调用debug()之前始终评估参数。
这里唯一的候选人是String.valueOf(entry[i])
,这也不是很贵,所以你可以说这个守卫是完全没必要的。
答案 3 :(得分:4)
像这样的日志记录语句的问题:
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
是要将值连接到String
会做很多工作,如果调试日志记录关闭则不会使用它。因此,在这种情况下,检查调试日志记录是否在执行此行之前是有益的。当你只是传递参数时:
logger.debug("The entry is {}.", entry);
然后它不需要构建一个从未使用过的String
,并且不需要检查;只是将参数传递给方法没有很高的开销。
请注意,如果在日志记录语句中对参数使用相对昂贵的表达式,则首先检查日志记录级别可能仍然有用。
答案 4 :(得分:3)
请不要使用if
语句,因为每次我查看这样的代码
if (logger.isDebug()) {
logger.debug("Of course it's debug {}", sadFace);
}
我哭了。
我希望创建静态字符串的成本非常低,对99%的用户来说都是微不足道的。