在这里帮我一个忙:)
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方法的静态字符串的成本(尽管更低)?
6条答案
按热度按时间hsvhsicv1#
我会试着从另一个Angular 提出我的看法
参数化日志究竟有什么好处?
您只需将**
toString()
调用和字符串连接**延迟到真正需要的时候,也就是您真正需要记录消息的时候。这样可以在禁用特定日志记录操作时优化性能。如果不确定,请检查source code for SLF4J。参数化日志是否会使guards在所有情况下都无用?
不知道
在哪些情况下日志保护会有用?
当存在其他潜在的昂贵操作时。
例如(在禁用此特定日志记录操作的情况下),如果我们有 no logging guard
1.我们将支付从
obj = getUserService().getCurrentUser()
开始的费用1.我们将保存成本从
"User name: " + obj.toString()
如果我们 * 使用logging guard*:
1.我们将支付
logger.isDebugEnabled()
的费用1.我们将从
obj = getUserService().getCurrentUser()
保存成本1.我们将保存成本从
"User name: " + obj.toString()
在后一种情况下,当启用这个特定的日志记录操作时,我们将以检查
isDebugEnabled()
两次的代价来保存这两种成本。注意:这只是一个例子,并不试图在这里讨论好的/坏的做法。
3gtaxfhh2#
写和阅读所有这些
if(logger.isDebugEnabled()) {}
可能花费的时间和它们保存的时间一样多。当然,调用log方法不是免费的,但调用
isDebugEnabled()
也是如此。因此,如果使用这种模式,您将为每个活动的log语句支付更多费用(因为日志框架将检查级别两次)。它也会使代码变得混乱。
在实践中,我还没有发现性能损失大到足以让人烦恼。
如果日志记录对您来说太慢,那么编写一个非阻塞的appender,它将日志事件推入队列,而不需要进行一些检查,并使用后台线程来处理它们。
背景:标准的appender都是同步的,因此在多线程应用程序中进行日志记录可能会导致许多小的暂停,其中所有线程都在等待将日志消息写入文件。
vxf3dgd43#
由于创建了字符串,因此未使用保护。
相反,它通常用于避免潜在的昂贵参数表达式,例如
entry[i].retrieveExtendedDebugInformation().formatNicely()
。为此,logback确保仅在实际打印日志消息时才计算参数,而log4j总是在调用debug()之前计算参数。这里唯一的候选者是
String.valueOf(entry[i])
,它也不是很昂贵,所以你可以说这个保护是完全不必要的。k3bvogb14#
像这样的日志语句的问题是:
它将做大量的工作来将值连接到
String
中,如果调试日志记录关闭,则永远不会使用String
。因此,在这种情况下,在执行这一行之前检查调试日志记录是否打开是有益的。当您只是传递参数时:则不需要建立一个从未使用过的
String
,不需要检查;仅仅将参数传递给方法并不具有非常高的开销。请注意,如果日志记录语句中的参数表达式相对昂贵,则首先检查日志记录级别可能仍然是有益的。
2nbm6dog5#
请不要使用
if
语句,因为每次我看这样的代码时我哭了。
我希望创建静态字符串的成本低到对99%的用户来说微不足道。
wn9m85ua6#
logger.isDebug()
的另一种替代方法是使用“lazy logging”或传递lambda表达式[ link ]: