что на самом деле делает log4j, когда мы включаем или выключаем некоторые места журнала? - PullRequest
10 голосов
/ 09 февраля 2010

Мы знаем, что можем настроить log4j для отключения журнала в определенных местах (класс или пакет в Java) через его свойства / файл конфигурации. Мои вопросы следуют:

  1. что на самом деле делает log4j для этих флагов?
  2. оператор журнала в log4j все еще вызывается, но просто не записывается в файл или консоль из-за этого флага? так все же влияют на производительность?
  3. это как #ifdef в C ++, которые вступают в силу во время компиляции, а затем могут ограничивать влияние на производительность?

спасибо,

Ответы [ 3 ]

16 голосов
/ 09 февраля 2010

Да, операторы журнала будут по-прежнему выполняться. Вот почему рекомендуется сначала проверить уровень журнала: что-то вроде

if (log.isInfoEnabled()) {
    log.info("My big long info string: " + someMessage);
}

Это необходимо для перераспределения пространства для информации String, когда уровень журнала не поддерживает INFO операторов.

Это совсем не то, что #ifdef - #ifdef - это директива компилятора, тогда как конфигурации Log4J обрабатываются во время выполнения.

Редактировать : Я ненавижу унижаться из-за невежества, поэтому вот одна статья, подтверждающая мой ответ.

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

В Log4J, если вы регистрируете сообщение на Уровень отладки и текущий Appender установлен только для регистрации сообщений INFO уровень и выше, то сообщение будет не будет отображаться Производительность штраф за вызов метода журнала само по себе минимально - несколько наносекунд. Тем не менее, это может занять больше времени, чтобы оцените аргументы в лог метод. Например:

logger.debug ("Большой объект «+ LargeObject.toString ()); * * тысячу двадцать-два

Оценка largeObject.toString () может быть медленным, и это оценивается раньше вызов в логгер, так логгер не может помешать его оценке, даже если он не будет использоваться.

Редактировать 2 : из самого руководства log4j (http://logging.apache.org/log4j/1.2/manual.html):

Пользователь должен знать о следующих проблемах производительности.

  1. Производительность ведения журнала при выключенном ведении журнала. Когда регистрация отключена полностью или только для набора уровней, стоимость запроса журнала состоит из вызова метода и целочисленного сравнения. На 233 МГц процессоре Pentium II эта стоимость обычно находится в диапазоне от 5 до 50 наносекунд.

    Однако вызов метода включает «скрытую» стоимость создания параметра.

    Например, для какой-то кошки-регистратора, пишущей,

     logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
    

    несет затраты на создание параметра сообщения, то есть преобразование как целого числа i и записи [i] в ​​строку, так и объединение промежуточных строк, независимо от того, будет ли сообщение записано в журнал или нет. Эта стоимость создания параметров может быть довольно высокой и зависит от размера используемых параметров.

    Чтобы избежать стоимости строительства параметра напишите:

    if(logger.isDebugEnabled() {
      logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
    }
    

    Это не приведет к затратам на создание параметров, если отладка отключена. С другой стороны, если в логгере включена отладка, он будет в два раза дороже оценивать, включен ли регистратор: один раз в debugEnabled и один раз в отладке. Это незначительные накладные расходы, потому что оценка регистратора занимает около 1% времени, необходимого для фактического ведения журнала.

5 голосов
/ 09 февраля 2010

Я провел простой тест для тестирования.

    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 с escape-анализом будет.

Однако я все равно не стал бы переносить операторы отладки в предложение if, если бы не было важным улучшение времени на полсекунды!

1 голос
/ 09 февраля 2010
  1. log4j обработает инструкцию log и проверит, включен ли конкретный регистратор на определенном уровне ведения журнала. Если это не так, то выписка не будет записана.

  2. Эти проверки значительно дешевле, чем фактическая запись на диск (или консоль), но они все еще оказывают влияние.

  3. нет, у java нет такого понятия, как #ifdef (в любом случае, из коробки есть прекомпиляторы java)

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