内置字符串格式与字符串串联作为日志记录参数 [英] Built-in string formatting vs string concatenation as logging parameter

查看:568
本文介绍了内置字符串格式与字符串串联作为日志记录参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 SonarLint 在下一行显示一个问题.

I'm using SonarLint that shows me an issue in the following line.

LOGGER.debug("Comparing objects: " + object1 + " and " + object2);

旁注:包含此行的方法可能会经常调用.

此问题的说明是

Side-note: The method that contains this line might get called quite often.

The description for this issue is

前提条件"和日志记录参数不需要评估 (鱿鱼:S2629)

"Preconditions" and logging arguments should not require evaluation (squid:S2629)

将需要进一步评估的消息参数传递到番石榴中 com.google.common.base.前提条件检查可能会导致性能下降 惩罚.这是因为每个参数是否需要它们 必须在实际调用该方法之前解决.

Passing message arguments that require further evaluation into a Guava com.google.common.base.Preconditions check can result in a performance penalty. That's because whether or not they're needed, each argument must be resolved before the method is actually called.

类似地,将串联的字符串传递到日志记录方法中也可以 造成不必要的性能损失,因为连接将 每次调用该方法时执行的操作,无论是否记录日志 级别低到足以显示消息.

Similarly, passing concatenated strings into a logging method can also incur a needless performance hit because the concatenation will be performed every time the method is called, whether or not the log level is low enough to show the message.

相反,您应该构建代码以传递静态或预先计算的代码 值进入前提条件"条件检查并记录调用.

Instead, you should structure your code to pass static or pre-computed values into Preconditions conditions check and logging calls.

具体地说,应该使用内置的字符串格式来代替 字符串连接,以及消息是否是方法的结果 调用,则先决​​条件应全部跳过,并且 相关的异常应该改为有条件地抛出.

Specifically, the built-in string formatting should be used instead of string concatenation, and if the message is the result of a method call, then Preconditions should be skipped altoghether, and the relevant exception should be conditionally thrown instead.

不兼容的代码示例

logger.log(Level.DEBUG, "Something went wrong: " + message);  // Noncompliant; string concatenation performed even when log level too high to show DEBUG messages

LOG.error("Unable to open file " + csvPath, e);  // Noncompliant

Preconditions.checkState(a > 0, "Arg must be positive, but got " + a); // Noncompliant. String concatenation performed even when a > 0

Preconditions.checkState(condition, formatMessage());  //Noncompliant. formatMessage() invoked regardless of condition

Preconditions.checkState(condition, "message: %s", formatMessage()); // Noncompliant

兼容解决方案

logger.log(Level.SEVERE, "Something went wrong: %s", message);  // String formatting only applied if needed

logger.log(Level.SEVERE, () -> "Something went wrong: " + message); //since Java 8, we can use Supplier , which will be evaluated lazily

LOG.error("Unable to open file {}", csvPath, e);

if (LOG.isDebugEnabled() {   LOG.debug("Unable to open file " + csvPath, e);  // this is compliant, because it will not evaluate if log level is above debug. }

Preconditions.checkState(arg > 0, "Arg must be positive, but got %d", a);  // String formatting only applied if needed

if (!condition) {   throw new IllegalStateException(formatMessage()); // formatMessage() only invoked conditionally }

if (!condition) {   throw new IllegalStateException("message: " + formatMessage()); }

我不确定100%是否理解这项权利.那么,为什么这确实是一个问题.尤其是有关使用字符串串联时性能下降的部分.因为我经常读到字符串连接比格式化它快.

I'm not 100% sure whether i understand this right. So why is this really an issue. Especially the part about the performance hit when using string concatenation. Because I often read that string concatenation is faster than formatting it.

编辑:也许有人可以向我解释两者之间的区别

Maybe someone can explain me the difference between

LOGGER.debug("Comparing objects: " + object1 + " and " + object2);

AND

LOGGEr.debug("Comparing objects: {} and {}",object1, object2);

在后台.因为我认为将在将String传递给方法之前先创建它.正确的?所以对我来说没有区别.但是显然我错了,因为SonarLint在抱怨它

is in the background. Because I think the String will get created before it is passed to the method. Right? So for me there is no difference. But obviously I'm wrong because SonarLint is complaining about it

推荐答案

我相信您的答案在那里.

I believe you have your answer there.

级联是预先计算条件检查的.因此,如果您有条件地将日志记录框架调用10K次,并且所有评估结果均为false,那么您将无缘无故地进行10K次连接.

Concatenation is calculated beforehand the condition check. So if you call your logging framework 10K times conditionally and all of them evaluates to false, you will be concatenating 10K times with no reason.

也请检查此主题.并检查Icaro答案的评论.

Also check this topic. And check Icaro's answer's comments.

也来看看 StringBuilder .

这篇关于内置字符串格式与字符串串联作为日志记录参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆