Sil*_*ior 192 java logging log4j
我在我的应用程序中使用Log4J进行日志记录.以前我使用调试调用如:
选项1:
logger.debug("some debug text");
Run Code Online (Sandbox Code Playgroud)
但有些链接表明最好先检查一下isDebugEnabled()
,例如:
选项2:
boolean debugEnabled = logger.isDebugEnabled();
if (debugEnabled) {
logger.debug("some debug text");
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是" 选项2能否以任何方式提高性能? ".
因为在任何情况下Log4J框架都对debugEnabled进行相同的检查.对于选项2,如果我们在单个方法或类中使用多个调试语句可能是有益的,其中框架不需要isDebugEnabled()
多次调用方法(在每次调用时); 在这种情况下,它只调用isDebugEnabled()
一次方法,如果Log4J配置为调试级别,那么实际上它调用isDebugEnabled()
方法两次:
我不认为如果我们logger.debug()
在方法或类中编写多个语句并debug()
根据选项1 调用方法,那么与选项2相比,它是Log4J框架的开销.因为它isDebugEnabled()
是一个非常小的方法(就代码而言),它可能是内联的好人选.
eri*_*son 230
在这种特殊情况下,选项1更好.
isDebugEnabled()
当涉及调用toString()
各种对象的方法并连接结果时,保护语句(检查)用于防止可能昂贵的日志消息计算.
在给定的示例中,日志消息是一个常量字符串,因此让记录器丢弃它与检查记录器是否已启用一样高效,并且由于分支较少,因此降低了代码的复杂性.
更好的是使用更新的日志记录框架,其中日志语句采用格式规范和由记录器替换的参数列表 - 但"懒惰",仅当记录器已启用时.这是slf4j采用的方法.
有关更多信息,请参阅我对相关问题的回答,以及使用log4j执行此类操作的示例.
Cek*_*eki 31
由于在方案1的消息字符串是一个常数,也绝对与条件包裹logging语句,相反没有收获,如果日志语句启用调试,你将被评估两次,一次是在isDebugEnabled()
方法和一次debug()
方法.调用的成本isDebugEnabled()
大约为5到30纳秒,对于大多数实际目的而言应该可以忽略不计.因此,选项2是不可取的,因为它会污染您的代码并且不会产生任何其他收益.
Ale*_*lex 17
isDebugEnabled()
通过连接字符串来构建日志消息时使用保留:
Var myVar = new MyVar();
log.debug("My var is " + myVar + ", value:" + myVar.someCall());
Run Code Online (Sandbox Code Playgroud)
但是,在您的示例中,没有速度增益,因为您只是记录字符串而不执行连接等操作.因此,您只是在代码中添加膨胀并使其更难阅读.
我个人在String类中使用Java 1.5格式调用,如下所示:
Var myVar = new MyVar();
log.debug(String.format("My var is '%s', value: '%s'", myVar, myVar.someCall()));
Run Code Online (Sandbox Code Playgroud)
我怀疑它有很多优化,但它更容易阅读.
请注意,尽管大多数日志记录API都提供了开箱即用的格式:例如,slf4j提供了以下内容:
logger.debug("My var is {}", myVar);
Run Code Online (Sandbox Code Playgroud)
这更容易阅读.
在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);
Run Code Online (Sandbox Code Playgroud)
简短版本:你可以做布尔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());
}
Run Code Online (Sandbox Code Playgroud)
这是它的javadoc
/**
* Check whether this category is enabled for the <code>DEBUG</code>
* Level.
*
* <p> This function is intended to lessen the computational cost of
* disabled log debug statements.
*
* <p> For some <code>cat</code> Category object, when you write,
* <pre>
* cat.debug("This is entry number: " + i );
* </pre>
*
* <p>You incur the cost constructing the message, concatenatiion in
* this case, regardless of whether the message is logged or not.
*
* <p>If you are worried about speed, then you should write
* <pre>
* if(cat.isDebugEnabled()) {
* cat.debug("This is entry number: " + i );
* }
* </pre>
*
* <p>This way you will not incur the cost of parameter
* construction if debugging is disabled for <code>cat</code>. On
* the other hand, if the <code>cat</code> is debug enabled, you
* will incur the cost of evaluating whether the category is debug
* enabled twice. Once in <code>isDebugEnabled</code> and once in
* the <code>debug</code>. This is an insignificant overhead
* since evaluating a category takes about 1%% of the time it
* takes to actually log.
*
* @return boolean - <code>true</code> if this category is debug
* enabled, <code>false</code> otherwise.
* */
Run Code Online (Sandbox Code Playgroud)
选项2更好.
本身并不能提高性能.但它确保性能不会降低.这是如何做.
通常我们期望logger.debug(someString);
但通常情况下,随着应用程序的增长,改变很多人,特别是新手开发人员,你可以看到
logger.debug(str1 + str2 + str3 + str4);
等等.
即使将日志级别设置为ERROR或FATAL,也会发生字符串串联!如果应用程序包含大量带有字符串连接的DEBUG级别消息,那么它肯定会受到性能影响,尤其是jdk 1.4或更低版本.(我不确定jdk internall的更高版本是否会执行任何stringbuffer.append()).
这就是为什么选项2是安全的.即使字符串连接也不会发生.
正如其他人所提到的,使用guard语句只有在创建字符串是一个耗时的调用时才真正有用.这个的具体例子是在创建字符串时会触发一些延迟加载.
值得注意的是,通过使用Simple Logging Facade for Java或(SLF4J) - http://www.slf4j.org/manual.html可以避免此问题.这允许方法调用,例如:
logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
Run Code Online (Sandbox Code Playgroud)
如果启用了调试,这只会将传入的参数转换为字符串.SLF4J顾名思义只是一个外观,日志调用可以传递给log4j.
您也可以非常轻松地"推出自己的"版本.
希望这可以帮助.
归档时间: |
|
查看次数: |
99581 次 |
最近记录: |