Издержки API ведения журнала Java - PullRequest
3 голосов
/ 26 апреля 2011

Я немного читал о различных способах записи сообщений об отладке с помощью Java, и, исходя из C, я обеспокоен следующим:

Эти библиотеки требуют минимальных накладных расходов в случае, когда ведение журнала отключено (например, в производственной среде), но, поскольку аргумент их функции log() все еще оценивается, я обеспокоен тем, что накладные расходы в реальном сценарии, фактически, ничуть не пренебрежимо.

Например, log(myobject.toString(), "info message") все еще имеет издержки на оценку myobject.toString(), что может быть довольно большим, даже если сама функция журнала ничего не делает.

У кого-нибудь есть решение этой проблемы?

PS: для тех, кто интересуется, почему я упомянул фон C: C позволяет использовать макрос препроцессора и инструкции во время компиляции, которые полностью удаляют весь код, связанный с отладкой во время компиляции, включая параметры макросов (которые просто не появятся при все).

РЕДАКТИРОВАТЬ: Прочитав первую партию ответов, кажется, что у java явно нет ничего, что могло бы сработать (подумайте о регистрации косинуса числа в большом цикле в мобильной среде, где важен каждый бит ЦП). Поэтому я добавлю, что я бы даже пошел на решение на основе IDE. Моим последним средством было создание чего-то вроде макроса "найти все / заменить". Сначала я подумал, что, возможно, что-то, взятое из аспектно-ориентированной среды, поможет ... Кто-нибудь ?

Ответы [ 5 ]

9 голосов
/ 26 апреля 2011

Я думаю, что FAQ по log4j хорошо справляется с этой задачей:

Для какого-то регистратора l, пишущего,

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

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

Если вас беспокоит скорость, напишите

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

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

Использование выражения guard является общим подходом, позволяющим избежать строкового конструирования.

Другие популярные фреймворки, такие как slf4j , используют подход с использованием форматированных строк / параметризованных сообщений , чтобы сообщение не оценивалось без необходимости.

4 голосов
/ 26 апреля 2011

Современные каркасы каротажа имеют переменную замену.В этом случае запись в журнал выглядит примерно так:

log.debug("The value of my first object is %s and of my second object is %s", firstObject, secondObject).

Функция toString () указанных объектов будет выполняться только тогда, когда для ведения журнала задано состояние отладки.В противном случае он просто проигнорирует параметры и вернется.

3 голосов
/ 26 апреля 2011

Ответ довольно прост: не вызывайте дорогостоящие методы в самом журнале.Кроме того, используйте охрану рядом с вызовом регистрации, если вы не можете избежать этого.

 if(logger.isDebugEnabled()) {
    logger.debug("this is an "+expensive()+" log call.");
 }

И, как уже отмечали другие, если у вас есть доступное форматирование в вашей структуре ведения журнала (т. Е. Если вы используетеодин достаточно современный, чтобы поддерживать его (который должен быть каждый из них , но это не так), вы должны полагаться на это, чтобы помочь покрыть расходы в момент регистрации.Если выбранный вами фреймворк не уже поддерживает форматирование, то либо переключите, либо напишите свою собственную оболочку.

2 голосов
/ 26 апреля 2011

Вы правы, оценивая аргументы для log() вызова , можете добавить ненужные издержки и может быть дорогим.

Вот почему большинство нормальных каркасов журналирования также предоставляют некоторые функции форматирования строк, так что вы можете написать что-то вроде этого:

log.debug("Frobnicating {0}", objectWithExpensiveToString);

Таким образом, ваши только накладные расходы - это вызов debug(). Если этот уровень деактивирован, то больше ничего не делается, и если он активирован, то строка формата интерпретируется, вызывается toString() на objectWithExpensiveToString(), и результат вставляется в строку формата перед его регистрацией.

Некоторые операторы журнала используют MessageFormat заполнителей стиля ({0}), другие используют format() style заполнителей (%s), а третьи могут использовать третий подход .

0 голосов
/ 26 апреля 2011

Вы можете использовать забавный способ - хотя и немного многословно - с утверждениями. При включенных утверждениях будут выводиться и накладные расходы, а при отключенных утверждениях нет вывода и абсолютно никаких служебных данных.

public static void main(String[] args) {
    assert returnsTrue(new Runnable() {
        @Override
        public void run() {
            // your logging code
        }
    });
}

public static boolean returnsTrue(Runnable r) {
    r.run();
    return true;
}

Здесь нужна функция returnTrue (), потому что я не знаю лучшего способа сделать выражение возвращаемым true, а assert требует логического значения.

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