что на самом деле делает log4j, когда мы включаем или выключаем некоторые места журнала?

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

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

спасибо,

10
задан 5YrsLaterDBA 9 February 2010 в 15:29
поделиться

3 ответа

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

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, если вы регистрируете сообщение на уровне DEBUG, и текущий Appender настроен на регистрацию только сообщений уровня INFO и выше, тогда сообщение не будет отображаться. Потеря производительности при вызове самого метода журнала минимальна - несколько наносекунд. Однако может потребоваться больше времени, чтобы оценить аргументы журнала { {1}} метод. Например:

logger.debug ("Большой объект " + largeObject.toString ());

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

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

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

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

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

    Например, для некоторого регистратора cat, запись

      logger.debug ("Номер записи:" + i + "равно" + String.valueOf (entry [i])); 
     

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

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

     if (logger.isDebugEnabled () {
    logger.debug ("Номер записи:" + i + "is" + String.valueOf (entry [i ])); 
    } 
     

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

16
ответ дан 3 December 2019 в 17:58
поделиться

Я запустил простой бенчмарк для проверки.

    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, если только улучшение времени порядка половины микросекунды не станет важным!

5
ответ дан 3 December 2019 в 17:58
поделиться
  1. log4j обработает оператор журнала и проверит, включен ли конкретный регистратор на определенном уровне ведения журнала. Если это не так, то выписка не будет регистрироваться.

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

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

1
ответ дан 3 December 2019 в 17:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: