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

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

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

спасибо,

Ответ 1

Да, операторы журнала все равно будут выполнены. Вот почему это хороший образец, чтобы сначала проверить уровень журнала: что-то вроде

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 выше и выше, то сообщение будет не отображается. Представление штраф за вызов метода журнала сама по себе минимальна - несколько наносекунд. Однако это может занять больше времени оценить аргументы в журнале метод. Например:

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

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

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

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

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

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

    Например, для некоторого logger cat, write,

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

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

    Чтобы избежать затрат на компоновку параметров, напишите:

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

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

Ответ 2

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

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

Ответ 3

  • log4j обработает оператор журнала и проверит, включен ли конкретный регистратор на определенном уровне ведения журнала. Если это не так, то инструкция не будет регистрироваться.

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

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