这里我将为logger.debug()添加logger.isDebugEnabled()条件语句。 但有时候循环中有很多logger.debug()。例如:
Logger log = Logger.getLogger(Test.class);
for(int i = 0; i < 1000; i++) {
...
log.debug("aaaaa");
...
for(int j = 0; i < 100; j++) {
...
log.debug("bbbb");
}
}
如果我直接添加,如下:
for(int i = 0; i < 1000; i++) {
...
if(log.isDebugEnabled()) {
log.debug("aaaaa");
}
...
for(int j = 0; i < 100; j++) {
...
if(log.isDebugEnabled()) {
log.debug("bbbb");
}
}
}
所以,在循环中,它会if()很多次。我怎么能用if(logger.isDebugEnabled())?
有没有人有想法?
感谢。
答案 0 :(得分:4)
我关心的是if()in循环是否会影响性能?
考虑以下代码:
boolean logging = log.isDebugEnabled();
for (int i = 0; i < 1000; i++) {
// stuff
if (logging) {
log.debug("Hi Mum!");
}
// more stuff
}
if
测试的成本可能只有2条指令,具体取决于JIT编译器的寄存器分配如何调整。这很可能是微不足道的,除非您正在进行荒谬的数量的日志记录。
但是,如果这些2到4条指令的性能损失真的很重要,那么你可以考虑:
完全取消对log
的调用,
使其以编译时常量为条件(以便优化器可以修剪代码),或
将测试从环路中提升出来;例如重构代码如下:
boolean logging = log.isDebugEnabled();
if (logging) {
for (int i = 0; i < 1000; i++) {
// stuff
log.debug("Hi Mum!");
// more stuff
}
} else {
for (int i = 0; i < 1000; i++) {
// stuff
// more stuff
}
}
然而,IMO,治愈方法比疾病更糟。
@ Vineet的观点也很重要。在实践中,这样的昂贵部分:
log.debug("Today is " + date);
是无论实际的日志记录级别如何,都会计算字符串连接表达式。除了if
测试之外,还有其他方法可以避免这种开销......虽然它们比缓存标志上的if
测试更昂贵。
答案 1 :(得分:2)
使用slf4j。
答案 2 :(得分:2)
将log.isDebugEnabled()
的值存储在本地变量中,如下所示:
// Calculate once and cache the answer
boolean areLogging = log.isDebugEnabled();
for (int i = 0; i < 1000; i++) {
...
if (areLogging) {
log.debug("aaaaa");
}
...
for (int j = 0; i < 100; j++) {
...
if (areLogging) {
log.debug("bbbb");
}
}
}
答案 3 :(得分:2)
已经指出使用slf4j。具体来说,您应该使用slf4j的“参数化消息”功能。
发布的代码未演示使用parameterized messages的实用程序。显然,“bbbb”将被视为字符串文字(因为编译器可以在运行时计算它的值并将其放在类的常量池中),当类加载并汇集到内部时,它将由JVM加载。字符串池;构建日志消息显然没有成本,log.isDebugEnabled()
调用是多余的。因此,我将使用更具描述性的示例来说明参数化消息的使用,以证明它的好处
for(int j = 0; i < 100; j++) {
...
if(log.isDebugEnabled()) { // this is required by log4j. Without this, on every iteration, a new String object will be created in the following statement.
log.debug("Loop counter is" + j); // This constructs a new String object only if DEBUG is enabled.
}
}
可以简化为:
for(int j = 0; i < 100; j++) {
...
log.debug("Loop counter is {}", j); //There is no explicit call to log.isDebugEnabled() in this case. The log message will be created only if DEBUG is enabled.
}
String literal Loop counter is {}
再次汇集在String intern池中,但在运行时,slf4j将创建值为Loop counter is 0
,Loop counter is 1
等的String对象,但前提是DEBUG级别已启用。