首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当我们打开或关闭一些日志位置时,log4j实际上在做什么?

当我们打开或关闭一些日志位置时,log4j实际上在做什么?
EN

Stack Overflow用户
提问于 2010-02-09 15:29:47
回答 3查看 2K关注 0票数 10

我们知道我们可以配置log4j,通过它的属性/配置文件关闭特定位置的日志(在Java中的类或包)。以下是我的问题:

  1. log4j实际上在为这些标志做什么?
  2. 是否仍然调用log4j中的日志语句,但只是因为该标志而没有被写入文件或控制台?那么仍然会对性能产生影响吗?
  3. 是否类似于在编译时生效的C++中的#ifdef,从而可以限制性能影响?

谢谢,

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-09 15:31:33

是的,日志语句仍将被执行。这就是为什么首先检查日志级别是一个很好的模式:

代码语言:javascript
运行
复制
if (log.isInfoEnabled()) {
    log.info("My big long info string: " + someMessage);
}

这是为了避免在日志级别不支持String语句时为info INFO重新分配空间。

它不像#ifdef - #ifdef是编译器指令,而Log4J配置是在运行时处理的。

编辑:我讨厌因为无知而被降级,所以这里有一篇文章支持我的答案。

来自http://surguy.net/articles/removing-log-messages.xml

中的Log4J,如果您在调试级别记录消息,并且当前的附录被设置为只记录信息级别及以上的消息,那么消息将不会显示。调用日志方法本身的性能损失最小-几纳秒。但是,计算日志方法的参数可能需要更长的时间。例如:

Logger.debug(“大对象是"+largeObject.toString());

计算largeObject.toString()可能很慢,并且在调用记录器之前对其进行评估,因此记录器不能阻止对其进行计算,即使它不会被使用。

编辑2:来自log4j手册本身(http://logging.apache.org/log4j/1.2/manual.html):

用户应该知道以下性能问题。

关闭日志记录时,

  1. 日志记录性能。当日志记录完全关闭或仅关闭一组级别时,日志请求的成本由一个方法调用和一个整数比较组成。在233个MHz奔腾II型机器上,这一成本通常在5到50纳秒的范围内。

然而,方法调用涉及到参数构造的“隐藏”成本。

例如,对于一些伐木猫,写作,

Logger.debug(“条目编号:”+i+“是”+String.valueOf(Entryi)“);

这将导致构造消息参数的成本,即将整数i和entryi转换为字符串,并连接中间字符串,而不管消息是否将被记录。这一参数建设成本可能相当高,这取决于所涉及的参数的大小。

为了避免参数的施工成本,写:

if(logger.isDebugEnabled() {logger.debug(“条目编号:”+i+“”是“+String.valueOf(Entryi)”);}

如果禁用调试,这将不会导致参数构造的成本。另一方面,如果记录器启用了调试,则评估是否启用记录器将花费两倍的成本:一次在debugEnabled中,一次在调试中。这是一个微不足道的开销,因为评估记录器所需的时间约为实际日志所需时间的1%。

票数 16
EN

Stack Overflow用户

发布于 2010-02-09 16:02:47

我运行了一个简单的基准测试。

代码语言:javascript
运行
复制
    for (int j = 0; j < 5; j++) {
        long t1 = System.nanoTime() / 1000000;
        int iterations = 1000000;
        for (int i = 0; i < iterations; i++) {
            int test = i % 10;
            log.debug("Test " + i + " has value " + test);
        }
        long t2 = System.nanoTime() / 1000000;
        log.info("elapsed time: " + (t2 - t1));

        long t3 = System.nanoTime() / 1000000;
        for (int i = 0; i < iterations; i++) {
            int test = i % 10;
            if (log.isDebugEnabled()) {
                log.debug("Test " + i + " has value " + test);
            }
        }
        long t4 = System.nanoTime() / 1000000;
        log.info("elapsed time 2: " + (t4 - t3));
    }

elapsed time: 539
elapsed time 2: 17
elapsed time: 450
elapsed time 2: 18
elapsed time: 454
elapsed time 2: 19
elapsed time: 454
elapsed time 2: 17
elapsed time: 450
elapsed time 2: 19

对于1.6.0_18,这让我感到惊讶,因为我以为内衬会阻止这件事。也许有转义分析的Java 7会。

但是,我仍然不会将调试语句包装在if子句中,除非时间的改进(半微秒级)变得重要了!

票数 5
EN

Stack Overflow用户

发布于 2010-02-09 15:41:52

  1. log4j将处理日志语句,并检查是否在特定日志记录级别启用了特定的记录器。如果不是,那么语句将不会被记录。
  2. 这些检查比实际写入磁盘(或控制台)要便宜得多,但它们仍然有影响。
  3. no,java没有像#ifdef这样的概念(反正有java预编译器)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2230180

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档