use*_*685 4 java performance logging log4j
我经常听到人们说,这是在日志记录时避免String Concatenation和使用的最佳实践之一{}。
我正在查看Log4j代码,以了解他们如何处理此问题,并认为他们正在做类似的事情。
这是format()方法的代码片段,其中包含模式和参数,并返回要记录的消息。
/**
* Formats arguments using SLF4J-like formatter.
* @param pattern pattern, may be malformed.
* @param arguments arguments.
* @return Message string
*/
private static String format(final String pattern,
final Object[] arguments) {
if (pattern != null) {
String retval = "";
int count = 0;
int prev = 0;
int pos = pattern.indexOf("{");
while(pos >= 0) {
if (pos == 0 || pattern.charAt(pos-1) != '\\') {
retval += pattern.substring(prev, pos);
if (pos + 1 < pattern.length() && pattern.charAt(pos+1) == '}') {
if(arguments != null && count < arguments.length) {
retval += arguments[count++];
} else {
retval += "{}";
}
prev = pos + 2;
} else {
retval += "{";
prev = pos + 1;
}
} else {
retval += pattern.substring(prev, pos - 1) + "{";
prev = pos + 1;
}
pos = pattern.indexOf("{", prev);
}
return retval + pattern.substring(prev);
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
我不明白这种实现比使用串联更好。任何对此的见解将非常有帮助。
在日志记录系统中格式化字符串的好处是,日志记录系统可以决定是否必须进行字符串连接。
让我们以这些行为例:
log.debug("Count: " + list.size());
log.debug("Count: {}", list.size());
Run Code Online (Sandbox Code Playgroud)
只要此记录器的级别为debug或更低,性能就没有区别,但是,如果日志级别高于debug,则第二行根本不会执行串联。
该问题的一些答案说明:
简短的版本是基于格式的用法更快,因为
Logger.debug("my name is {}", name);
Run Code Online (Sandbox Code Playgroud)
仅在 log4j决定需要记录该事件之后,才进行昂贵的字符串重击;例如,在根据日志记录级别进行过滤之后,等等。
相比之下,使用字符串串联版本
Logger.debug("my name is " + name);
Run Code Online (Sandbox Code Playgroud)
计算参数时会发生字符串重击。因此,即使在没有实际记录任何事件的情况下,它也会发生。(您可以在代码中使用保护措施来部分避免这种情况,但这会使日志记录代码变得冗长。)
但是看看这个例子:
log.debug("Count: " + list.size());
log.debug("Count: {}", list.size());
Run Code Online (Sandbox Code Playgroud)
格式版本会更快,但是两个版本始终会评估list.size()表达式。如果那是一个昂贵的手术,那么您可能需要求助于使用警卫。例如
if (log.isDebugEnabled()) {
log.debug("Count: " + list.size());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1093 次 |
| 最近记录: |