производительность log4j - PullRequest
12 голосов
/ 16 июня 2010

Я занимаюсь разработкой веб-приложения, и я хотел бы зарегистрировать некоторую информацию, чтобы помочь мне улучшить и наблюдать за приложением. (Я использую 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 if (i == 9999).

Когда номер_потока равен 10, существует 100 000 журналов и тестов и конкатенаций. Когда это 100, есть 1.000.000 входов и если тесты и объединения. (Я где-то читал, что JVM использует присоединение StringBuilder для конкатенации, а не простой конкатенации).

Я что-то пропустил? Я делаю что-то неправильно? Я забыл какой-либо фактор, который может снизить производительность? Если эти цифры верны, я думаю, мне не нужно беспокоиться о производительности log4j, даже если я сильно захожу, не так ли?

Я читал, что: «Типичная стоимость регистрации составляет от 100 до 300 микросекунд». Это правильно? ( log4J руководство )

Ответы [ 7 ]

12 голосов
/ 16 июня 2010

Если производительность вызывает беспокойство, не забудьте уделить особое внимание документации макета шаблона и избегать дорогостоящих символов преобразования, таких как 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 () в начале, но строка, переданная в качестве параметра, должна быть полностью построена, прежде чем эта проверка может произойти, что приведет к ненужной задержке при отключении уровня отладки.

4 голосов
/ 16 июня 2010

Мне не нужно беспокоиться о производительности log4j, даже если я интенсивно регистрирую

Точно.Не оптимизируйте, пока результаты профилирования не скажут вам.Бывают случаи, когда производительность журналирования является узким местом, но сначала вам нужно попасть в этот случай, а затем оптимизировать его.

4 голосов
/ 16 июня 2010

Да, Log4J, как известно, работает быстро благодаря сознательным усилиям его разработчиков.См. Также раздел «Производительность» в конце этого введения в Log4J .

1 голос
/ 16 июня 2010

горлышко бутылки должно быть на жестком диске.ваш тест показывает примерно 1 МБ / с скорость записи на диск, что на самом деле довольно плохо.

0 голосов
/ 12 февраля 2015

Следует отметить, что log4j страдает от многочисленных болей при сильном одновременном использовании.

Более подробная информация и некоторые обходные пути в моем другом ответе: Файл производственных настроек для log4j?

0 голосов
/ 16 июня 2010

Если производительность действительно важна, взгляните на slf4j: http://www.slf4j.org/manual.html

Благодаря подходу заполнителя они быстрее, чем log4j, когда вы отключили запись этих сообщений, потому что в log4j объединение строк происходит независимо друг от друга.сообщение действительно нужно.Slf4j заменяет заполнитель только в том случае, если это сообщение будет действительно зарегистрировано.

Но вы можете сделать что-то подобное в log4j:

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

Но я думаю, что это много шаблонного кода, поэтому яиспользую slf4j

0 голосов
/ 16 июня 2010

Убедитесь, что у вас есть правильная стратегия ведения журнала.Это означает, что вы должны определить, что регистрировать, и разделить его на отладку, трассировку, информацию, предупреждение и ошибку, а также некоторые другие, если они вам нужны.Также убедитесь, что вы даете возможность включать и выключать его, чтобы при необходимости включить производительность / отладку.

Ведение журнала может оказать значительное влияние на интенсивно используемый сайт / приложение. Кроме того, ведение журнала слишком много дает вам больше информации, чемВы можете разобраться.Иногда ведение журнала является единственным инструментом отладки после инцидента, поэтому убедитесь, что он учитывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...