【问题标题】:log4j performancelog4j 性能
【发布时间】:2010-06-16 12:20:04
【问题描述】:

我正在开发一个网络应用程序,我想记录一些信息来帮助我改进和观察该应用程序。 (我用的是Tomcat6)

首先我想我会使用 StringBuilders,将日志附加到它们,然后一个任务会将它们保存到数据库中,就像每 2 分钟一样。因为我担心开箱即用的日志记录系统的性能。然后我做了一些测试。尤其是 log4j。

这是我的代码:

Main.java

public static void main(String[] args) {
  Thread[] threads = new Thread[LoggerThread.threadsNumber];

  for(int i = 0; i < LoggerThread.threadsNumber; ++i){
   threads[i] = new Thread(new LoggerThread("name - " + i));
  }
  LoggerThread.startTimestamp = System.currentTimeMillis();

  for(int i = 0; i < LoggerThread.threadsNumber; ++i){
   threads[i].start();
  }

LoggerThread.java

public class LoggerThread implements Runnable{
 public static int threadsNumber = 10;
 public static long startTimestamp;
 private static int counter = 0;
 private String name;

 public LoggerThread(String name) {
  this.name = name;
 }
 private Logger log = Logger.getLogger(this.getClass());

 @Override
 public void run() {
  for(int i=0; i<10000; ++i){
   log.info(name + ": " + i);

   if(i == 9999){
    int c = increaseCounter();

    if(c == threadsNumber){
     System.out.println("Elapsed time: " + 
       (System.currentTimeMillis() - startTimestamp));
    }
   }

  }
 }

 private synchronized int increaseCounter(){
  return ++counter;
 }

}
     }

log4j.properties

log4j.logger.main.LoggerThread=debug, f
log4j.appender.f=org.apache.log4j.RollingFileAppender
log4j.appender.f.layout=org.apache.log4j.PatternLayout
log4j.appender.f.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.appender.f.File=c:/logs/logging.log
log4j.appender.f.MaxFileSize=15000KB
log4j.appender.f.MaxBackupIndex=50

我认为这是 log4j 的一个非常常见的配置。 首先我使用 log4j 1.2.14 然后我意识到有一个更新的版本,所以我切换到 1.2.16

这里是数字(都是毫秒)

LoggerThread.threadsNumber = 10

1.2.14: 4235, 4267, 4328, 4282
1.2.16: 2780, 2781, 2797, 2781

LoggerThread.threadsNumber = 100

1.2.14: 41312, 41014, 42251
1.2.16: 25606, 25729, 25922

我认为这非常快。不要忘记:在每个循环中,run 方法不仅仅是登录文件,它还必须连接字符串 (name + ": " + i),并检查 if 测试 (i == 9999)

当threadsNumber 为10 时,有100.000 个日志记录以及if 测试和连接。当它为 100 时,有 1.000.000 个日志记录以及 if 测试和连接。 (我在某处读过 JVM 使用 StringBuilder 的 append 进行连接,而不是简单的连接)。

我错过了什么吗?难道我做错了什么?我是否忘记了任何可能降低性能的因素? 如果这些数字是正确的,我认为即使我大量登录也不必担心 log4j 的性能,不是吗?

我读到过:“实际记录的典型成本约为 100 到 300 微秒。”这是正确的吗? (log4J manual)

【问题讨论】:

    标签: java performance log4j


    【解决方案1】:

    如果关注性能,请务必特别注意模式布局文档,并避免使用昂贵的转换字符,例如 C、F、L 和 M。这些需要恶作剧来检索此信息。

    使用 c 代替 C,并在创建 Logger 对象时适当地命名它们。这意味着您不能从父类继承记录器,但是重新定义记录器带来的不便值得提高性能。 F、L 和 M 的功能没有简单的替代品,但措辞良好的日志消息应该很容易在您的源代码中找到,因此减少了指定确切方法、文件和行的需要。

    最后,避免在日志消息中使用动态字符串连接。当需要使用连接时,一定要在适当的检查器方法中包装该日志记录字符串的创建。

    private final static Logger LOG = Logger.get(MyClass.class);
    ...
    void someMethod() {
        if (LOG.isDebugEnabled()) {
            LOG.debug("some really expensive string concatenation: " + someInstanceVariable + " a bunch of other text!");
        }
    }
    

    isDebugEnabled() 总是在恒定时间内运行。 LOG.debug() 本身在开始时本质上会进行 isDebugEnabled() 检查,但作为参数传递的字符串必须在该检查发生之前完全构建,从而在关闭调试级别时造成不必要的延迟。

    【讨论】:

    • C、F、L 和 M 到底有多慢?
    【解决方案2】:

    是的,众所周知,Log4J 的速度很快,这归功于其实现者的有意识的努力。另请参阅introduction to Log4J 末尾的“性能”部分。

    【讨论】:

    • 是的,我已经更新了我的问题,我不敢相信它是 100-300 毫秒的记录时间。 (egyébként köszönöm)
    • 我还没有仔细检查过这个数字——到目前为止,Log4J 的运行速度已经足够快了,所以我从来不需要担心它的性能。我同意@unbeli 的观点,只有当您确实遇到性能问题并且您已经(使用分析器)验证瓶颈是日志记录时,才值得优化日志记录。 Szívesen máskor 是:-)
    【解决方案3】:

    我不必担心 log4j 的问题 即使我大量登录也能表现出色

    没错。在您的分析结果告诉您之前不要优化。在某些情况下,日志记录性能是一个瓶颈,但您需要先解决这种情况,然后针对它进行优化。

    【讨论】:

      【解决方案4】:

      瓶颈应该是硬盘。您的测试显示大约 1MB/s 的磁盘写入速度,这实际上很差。

      【讨论】:

      • 你能分享一下数学吗?
      【解决方案5】:

      确保您有正确的日志记录策略。这意味着确保您定义要记录的内容并将其分为调试、跟踪、信息、警告和错误以及其他一些(如果需要)。还要确保您能够根据需要打开和关闭它以执行性能/调试。

      日志记录可能会对频繁使用的网站/应用程序产生重大影响,而且日志记录过多会为您提供比您可以整理的更多信息。有时,日志记录是您拥有的唯一事件后调试工具,因此请确保将其发挥作用。

      【讨论】:

        【解决方案6】:

        如果性能真的很重要,请查看 slf4j: http://www.slf4j.org/manual.html

        使用他们的占位符方法,当您禁用记录这些消息时,它们比 log4j 更快,因为在 log4j 中,字符串连接独立发生,消息确实是需要的。 Slf4j 仅在此消息将被真正记录时替换占位符。

        但是你可以在 log4j 中做这样的事情:

        if(l.isDebugEnabled()) l.debug("log entry: " + 7);
        

        但我认为这是很多样板代码,所以我使用的是 slf4j

        【讨论】:

          【解决方案7】:

          必须注意,log4j 在大量并发使用时会遇到许多锁定问题。

          我的另一个答案中的更多详细信息和一些解决方法: Production settings file for log4j?

          【讨论】:

            猜你喜欢
            • 2016-11-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-19
            • 2012-06-22
            • 2012-05-11
            相关资源
            最近更新 更多