gpt4 book ai didi

java - 将 logger.debug ("message: "+ 文本)转换为 logger.debug(消息 : {}", 文本)

转载 作者:行者123 更新时间:2023-12-01 13:27:51 29 4
gpt4 key购买 nike

我正在尝试找到解决由于使用以下形式的代码而导致的冗余字符串连接问题的最佳方法:

logger.debug("Entering loop, arg is: " + arg) // @1

在大多数情况下,logger.level 高于 debug,并且 arg.toString() 和字符串连接是一种浪费,耗尽 CPU 周期并短暂耗尽内存。

在引入可变参数之前,推荐的方法是首先测试记录器级别:

if (logger.isDebugEnabled())    
logger.debug("Entering loop, arg is: " + arg); // @2

但现在首选的形式是

  logger.debug("Entering loop, arg is: {}", arg); // @3

在脚本中为每个 logger.debug 加上 if (logger.isDebugEnabled()) (以及其他方法的等价物)前缀并不是很困难,但是我正在尝试找到将第一种形式转换为第三种形式的最佳方法。

有什么建议吗?挑战在于在格式字符串中插入正确的数字大括号对 {}。我希望 logback 能够在末尾附加占位符未涵盖的剩余参数,但我找不到它执行此操作的引用。

作为替代方案,我正在考虑编写一个粘贴在末尾的类Concatenator并将第一种形式转换为

logger.debug(new Concatenator("Entering loop, arg is: ", arg)); // @4

Concatenator 类延迟对 arg.toString() 的调用和字符串连接,直到 logger 调用 toString(),从而在记录器处于较高过滤级别时避免这两种情况。它确实增加了创建 Object[]Concatenator 的开销,但这应该比替代方案便宜。

问题:

  • 我认为这个转换(@1->@4 - 将+替换为并包含在new Contatenator( ...)) 更容易。我有什么遗漏的吗?
  • @4@1 好得多,我这样说对吗?
public class Concatenator {
final Object[] input;
String output;
public Concatenator(Object... input) {
this.input = input;
}
public String toString() {
if (output == null) {
StringBuffer b = new StringBuffer();
for (Object s : input) b.append(s.toString());
output = b.toString();
}
return output;
}
public static void main(String args[]) {
new Concatenator("a", "b", new X());
System.out.println(new Concatenator("c", "d", new X()));
}
}
class X {
public String toString() {
System.out.println("X.toString");
return super.toString();
}
}

最佳答案

不幸的是,你的方法不会改变任何事情。事实上,它引入了一个额外的对象实例化/分配(您的连接器)。您还使用了 StringBuffer ,它引入了您不需要的同步开销。

问题出在 SLF4J 的 Logger.debug() 调用的方法签名上。第一个参数始终是String。这意味着您必须调用:

logger.debug(new Concatenator("Entering loop, arg is: ", arg).toString());

这意味着...您所做的事情与 Java 要做的事情完全相同,但开销更大。

Java 编译器通过创建 StringBuilder 并执行您在 Concatenator 中所做的操作来处理字符串连接运算符 (+) toString() 上的类。

logger.debug("Entering loop, arg is: " + arg);

变成:

logger.debug(new StringBuilder()
.append("Entering loop, arg is: ")
.append(arg).toString());

(如果您使用 javap 查看生成的字节码,您会发现情况就是如此。)

因此,您当前的方法将比现在的方法更昂贵。

编辑:因此,完成这项工作的方法是......

logger.debug("{}", new Concatenator("Entering loop, arg is: ", arg));

这样,您的Concatenator就会作为Object传递,除非记录器需要,否则不会调用它的toString()。另外,将类中的 StringBuffer 替换为 StringBuilder

如果我没有直接回答你的问题......这比原来的更好吗? 可能;除非需要,否则不会发生字符串连接。然而,您正在引入对象实例化/分配。查看差异的唯一真正方法是对其进行分析/编写基准。

关于java - 将 logger.debug ("message: "+ 文本)转换为 logger.debug(消息 : {}", 文本),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21718213/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com