当前位置:  开发笔记 > 编程语言 > 正文

在log4j中,在记录改进性能之前检查isDebugEnabled吗?

如何解决《在log4j中,在记录改进性能之前检查isDebugEnabled吗?》经验,为你挑选了7个好方法。

我在我的应用程序中使用Log4J进行日志记录.以前我使用调试调用如:

选项1:

logger.debug("some debug text");

但有些链接表明最好先检查一下isDebugEnabled(),例如:

选项2:

boolean debugEnabled = logger.isDebugEnabled();
if (debugEnabled) {
    logger.debug("some debug text");
}

所以我的问题是" 选项2能否以任何方式提高性能? ".

因为在任何情况下Log4J框架都对debugEnabled进行相同的检查.对于选项2,如果我们在单个方法或类中使用多个调试语句可能是有益的,其中框架不需要isDebugEnabled()多次调用方法(在每次调用时); 在这种情况下,它只调用isDebugEnabled()一次方法,如果Log4J配置为调试级别,那么实际上它调用isDebugEnabled()方法两次:

    如果为debugEnabled变量赋值,和

    实际上是由logger.debug()方法调用的.

我不认为如果我们logger.debug()在方法或类中编写多个语句并debug()根据选项1 调用方法,那么与选项2相比,它是Log4J框架的开销.因为它isDebugEnabled()是一个非常小的方法(就代码而言),它可能是内联的好人选.



1> erickson..:

在这种特殊情况下,选项1更好.

isDebugEnabled()当涉及调用toString()各种对象的方法并连接结果时,保护语句(检查)用于防止可能昂贵的日志消息计算.

在给定的示例中,日志消息是一个常量字符串,因此让记录器丢弃它与检查记录器是否已启用一样高效,并且由于分支较少,因此降低了代码的复杂性.

更好的是使用更新的日志记录框架,其中日志语句采用格式规范和由记录器替换的参数列表 - 但"懒惰",仅当记录器已启用时.这是slf4j采用的方法.

有关更多信息,请参阅我对相关问题的回答,以及使用log4j执行此类操作的示例.


log5j扩展log4j的方式与slf4j非常相似
@SnakeDoc否.它是方法调用的基础:方法arg-lists中的表达式在调用之前被有效地计算.如果这些表达式是a)被认为是昂贵的并且b)仅在某些条件下需要(例如,当启用调试时),那么您唯一的选择是对调用进行条件检查,并且框架不能为您执行此操作.基于格式化程序的日志方法的一点是你可以传递一些Object(基本上是免费的),只有在需要时,logger才会调用`toString()`.

2> Ceki..:

由于在方案1的消息字符串是一个常数,也绝对与条件包裹logging语句,相反没有收获,如果日志语句启用调试,你将被评估两次,一次是在isDebugEnabled()方法和一次debug()方法.调用的成本isDebugEnabled()大约为5到30纳秒,对于大多数实际目的而言应该可以忽略不计.因此,选项2是不可取的,因为它会污染您的代码并且不会产生任何其他收益.



3> Alex..:

isDebugEnabled()通过连接字符串来构建日志消息时使用保留:

Var myVar = new MyVar();
log.debug("My var is " + myVar + ", value:" + myVar.someCall());

但是,在您的示例中,没有速度增益,因为您只是记录字符串而不执行连接等操作.因此,您只是在代码中添加膨胀并使其更难阅读.

我个人在String类中使用Java 1.5格式调用,如下所示:

Var myVar = new MyVar();
log.debug(String.format("My var is '%s', value: '%s'", myVar, myVar.someCall()));

我怀疑它有很多优化,但它更容易阅读.

请注意,尽管大多数日志记录API都提供了开箱即用的格式:例如,slf4j提供了以下内容:

logger.debug("My var is {}", myVar);

这更容易阅读.


使用String.format(...),同时使日志行更容易阅读,实际上可能会以一种糟糕的方式影响性能.SLF4J执行此操作的方式将参数发送到logger.debug方法,并且在构造字符串之前完成isDebugEnabled的评估.使用String.format(...)的方式,在完成对logger.debug的方法调用之前,将构造字符串,这样即使调试级别为,也将支付字符串构建的代价.没有启用.对不起挑选,只是为了避免新手混淆;-)

4> cybaek..:

在Java 8中,您不必使用它isDebugEnabled()来提高性能.

https://logging.apache.org/log4j/2.0/manual/api.html#Java_8_lambda_support_for_lazy_logging

import java.util.logging.Logger;
...
Logger.getLogger("hello").info(() -> "Hello " + name);



5> Andrew Carr..:

简短版本:你可以做布尔isDebugEnabled()检查.

理由:
1-如果复杂的逻辑/字符串连续.已添加到您的调试语句中,您已经有了检查.
2-您不必有选择地在"复杂"调试语句中包含该语句.所有陈述都包含在内.
3-在记录之前调用log.debug执行以下操作:

if(repository.isDisabled(Level.DEBUG_INT))
return;

这与调用日志基本相同.还是猫 isDebugEnabled().

然而!这就是log4j开发人员的想法(因为它是在他们的javadoc中,你可能应该选择它.)

这是方法

public
  boolean isDebugEnabled() {
     if(repository.isDisabled( Level.DEBUG_INT))
      return false;
    return Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel());
  }

这是它的javadoc

/**
*  Check whether this category is enabled for the DEBUG
*  Level.
*
*  

This function is intended to lessen the computational cost of * disabled log debug statements. * *

For some cat Category object, when you write, *

*      cat.debug("This is entry number: " + i );
*  
* *

You incur the cost constructing the message, concatenatiion in * this case, regardless of whether the message is logged or not. * *

If you are worried about speed, then you should write *

*    if(cat.isDebugEnabled()) {
*      cat.debug("This is entry number: " + i );
*    }
*  
* *

This way you will not incur the cost of parameter * construction if debugging is disabled for cat. On * the other hand, if the cat is debug enabled, you * will incur the cost of evaluating whether the category is debug * enabled twice. Once in isDebugEnabled and once in * the debug. This is an insignificant overhead * since evaluating a category takes about 1%% of the time it * takes to actually log. * * @return boolean - true if this category is debug * enabled, false otherwise. * */



6> Sathya..:

选项2更好.

本身并不能提高性能.但它确保性能不会降低.这是如何做.

通常我们期望logger.debug(someString);

但通常情况下,随着应用程序的增长,改变很多人,特别是新手开发人员,你可以看到

logger.debug(str1 + str2 + str3 + str4);

等等.

即使将日志级别设置为ERROR或FATAL,也会发生字符串串联!如果应用程序包含大量带有字符串连接的DEBUG级别消息,那么它肯定会受到性能影响,尤其是jdk 1.4或更低版本.(我不确定jdk internall的更高版本是否会执行任何stringbuffer.append()).

这就是为什么选项2是安全的.即使字符串连接也不会发生.



7> Pablojim..:

正如其他人所提到的,使用guard语句只有在创建字符串是一个耗时的调用时才真正有用.这个的具体例子是在创建字符串时会触发一些延迟加载.

值得注意的是,通过使用Simple Logging Facade for Java或(SLF4J) - http://www.slf4j.org/manual.html可以避免此问题.这允许方法调用,例如:

logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);

如果启用了调试,这只会将传入的参数转换为字符串.SLF4J顾名思义只是一个外观,日志调用可以传递给log4j.

您也可以非常轻松地"推出自己的"版本.

希望这可以帮助.

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有