Java 即使使用slf4j,您是否应该保护日志记录?
在这里的辩论中帮助我……) 这里的slf4j站点表明,由于参数化日志记录,日志保护是不必要的。也就是说,不要写:Java 即使使用slf4j,您是否应该保护日志记录?,java,performance,logging,slf4j,Java,Performance,Logging,Slf4j,在这里的辩论中帮助我……) 这里的slf4j站点表明,由于参数化日志记录,日志保护是不必要的。也就是说,不要写: if(logger.isDebugEnabled()) { logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); } 你可以逃脱: Object entry = new SomeObject(); logger.debug("The entry is {}.", entry); 这真的没
if(logger.isDebugEnabled()) {
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
你可以逃脱:
Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);
这真的没问题吗,还是会导致创建传递给跟踪方法的静态字符串的成本(尽管更低)?请不要使用
if
语句,因为每次我看到这样的代码时
if (logger.isDebug()) {
logger.debug("Of course it's debug {}", sadFace);
}
我哭了
我希望创建静态字符串的成本非常低,对99%的用户来说微不足道。如果(logger.isDebugEnabled()){}编写和读取所有这些
if(logger.isDebugEnabled()){}
可能会花费与它们节省您同样多的时间
当然,调用log方法不是免费的,但是调用isDebugEnabled()
也是免费的。因此,如果您使用此模式,您将为每个活动的日志语句支付更多的费用(因为日志框架将检查两次级别)
它还使代码混乱
在实践中,我还没有发现对表现的惩罚会大到足以令人烦恼的程度
如果日志记录对您来说太慢,请编写一个非阻塞appender,将日志事件推送到队列中,而无需进行少量检查,并使用后台线程来处理它们
背景:标准appender都是同步的,因此在多线程应用程序中登录可能会导致许多小暂停,所有线程都会等待将日志消息写入文件。像这样的日志语句的问题:
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
将值连接到字符串
,这将做大量工作,如果调试日志记录处于关闭状态,则永远不会使用该字符串。因此,在这种情况下,在执行这一行之前检查调试日志记录是否打开是有益的。当您只是传递参数时:
logger.debug("The entry is {}.", entry);
这样就不必构建一个从未使用过的字符串
,也不需要进行检查;仅仅将参数传递给方法不会有很高的开销
请注意,如果日志语句中的参数表达式相对昂贵,那么最好先检查日志记录级别。由于创建了字符串,因此未使用保护 相反,它通常用于避免潜在的昂贵参数表达式,如
entry[i].retrieveextendededebuginformation().formatwelly()
。为此,logback确保只有在实际打印日志消息时才计算参数,而log4j总是在调用debug()之前计算参数
这里唯一的候选者是
String.valueOf(entry[i])
,它也不是很贵,因此您可以提出一个论点,即这个防护完全不必要。我将试着从另一个角度讲我的两分钱
参数化日志记录的确切好处是什么?
您只需延迟toString()
调用和字符串连接,直到真正需要时,也就是您真正需要记录消息的时候。这可以在禁用特定日志记录操作时优化性能。如果不确定,请检查
参数化日志记录是否会使防护在所有情况下都无效?
没有
在哪些情况下会使用日志保护?
当存在其他潜在的昂贵操作时
例如(在禁用此特定日志操作的情况下),如果我们没有日志保护
obj=getUserService().getCurrentUser()
“用户名:”+obj.toString()
logger.isDebugEnabled()
obj=getUserService().getCurrentUser()的成本
“用户名:”+obj.toString()
isDebugEnabled()
为代价节省这两项成本
注意:这只是一个例子,这里不讨论好的/坏的做法。谢谢,我也是这么想的。。在我给你一个加号之前,我将等待着看一下一般用户的想法:)我喜欢关于附加器的提示,这对我们来说可能是个问题。我认为,通过一些JIT优化,“调用日志方法”和“调用isDebugEnabled()”实际上都是免费的。我不确定,但如果是为sl4jf提供实际高性能实现的人,我会在禁用级别的rutime中放置一个没有op方法的实现,以便JIT可以删除调用。好的-这是有意义的,这是另一种观点。所以在你看来,这是一个判断是否需要保护的决定,而保护只应用于相对罕见(昂贵)的操作?。。参数的引入减少了这些操作的数量。是的,并且取决于操作的成本,通常只有在循环内跟踪语句时才有意义。有人甚至可能会争辩说,如果您的调试语句非常昂贵,以至于即使在更高的日志级别上,它们也会减慢类的速度,那么您没有正确地使用log.debug,特别是,您可能在(condition){log.debug(complexidexpression);doSomething();}的同时(condition){log.debug(complexing);doSomething();},而您应该在执行
log.debug(complexidexpression);while(condition){log.trace(simpleExpression);doSomething();}
。但我不是狂热者,我承认我经常写一个守卫。“不是很贵”对于一个有大量日志语句的程序来说,仍然是非常昂贵的。logback如何防止在方法调用之前对参数求值?在log4j的log.debug(“条目是:”+Entry);
中,必须在调用l之前构造参数
logger.debug("User name: {}", getUserService().getCurrentUser());
if (logger.isDebugEnabled()) {
logger.debug("User: {}", getUserService().getCurrentUser());
}