即使使用slf4j,你应该保护你的日志吗?

Mar*_*k D 34 java performance logging slf4j

在这里帮我辩论.. :)

这里的slf4j站点http://www.slf4j.org/faq.html#logging_performance表示由于参数化日志记录,不需要日志记录保护.即不是写作:

if(logger.isDebugEnabled()) {
  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}
Run Code Online (Sandbox Code Playgroud)

你可以逃脱:

Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);
Run Code Online (Sandbox Code Playgroud)

这真的没问题,或者它是否会产生(虽然更低)创建传递给trace方法的静态字符串的成本..?

fgl*_*lez 48

我会尝试从另一个角度来看待我的两分钱

参数化日志记录的好处是什么?

您只需将toString()调用字符串连接推迟到真正需要,这时您必须记录消息.这将在禁用特定日志记录操作时优化性能.如果不确定,请检查SLF4J的源代码.

参数化日志记录是否会使警卫在所有情况下都无用?

没有.

在哪些情况下,伐木卫兵会被使用?

当还有其他潜在的昂贵操作时.

例如(如果禁用此特定日志记录操作),如果我们没有日志记录保护

logger.debug("User name: {}", getUserService().getCurrentUser());
Run Code Online (Sandbox Code Playgroud)
  1. 我们会从中支付费用obj = getUserService().getCurrentUser()
  2. 我们会节省成本 "User name: " + obj.toString()

如果我们使用伐木守卫:

if (logger.isDebugEnabled()) {
    logger.debug("User: {}", getUserService().getCurrentUser());
}
Run Code Online (Sandbox Code Playgroud)
  1. 我们会支付费用logger.isDebugEnabled()
  2. 我们会节省成本obj = getUserService().getCurrentUser()
  3. 我们会节省成本 "User name: " + obj.toString()

在后一种情况下,isDebugEnabled()当启用此特定日志记录操作时,我们将以检查两次的代价来节省成本.

注意:这只是一个例子,而不是在这里讨论好/坏做法.


Aar*_*lla 18

编写和阅读所有这些if(logger.isDebugEnabled()) {}内容可能会花费他们拯救你的时间.

当然,调用log方法并不是免费的,但调用也是如此isDebugEnabled().所以你付出更多,如果你使用这个模式(因为日志框架将检查标准的两倍),这是积极的每个日志语句.

它也使代码混乱.

在实践中,我没有发现性能损失足以打扰.

如果日志记录对您来说太慢,请编写一个非阻塞的appender,将日志事件推送到队列中,而不需要几次检查,并使用后台线程来处理它们.

背景:标准的appender都是同步的,因此登录多线程应用程序会导致许多小的暂停,其中所有线程都等待将日志消息写入文件.


wal*_*orn 8

由于创建了字符串,因此不使用防护.

相反,它通常用于避免可能昂贵的参数表达式,例如entry[i].retrieveExtendedDebugInformation().formatNicely().为此,logback确保仅在实际打印日志消息时评估参数,而log4j在调用debug()之前始终评估参数.

这里唯一的候选人String.valueOf(entry[i]),也不是很贵,所以你可以说这个守卫是完全没必要的.