Logger slf4j преимущества форматирования с {} вместо конкатенации строк
Есть ли преимущество использования {}
вместо конкатенации строк?
Пример из slf4j
logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
вместо
logger.debug("Temperature set to"+ t + ". Old temperature was " + oldT);
Я думаю, что речь идет об оптимизации скорости, потому что можно избежать оценки параметров (и конкатенации строк) во время выполнения, в зависимости от файла конфигурации. Но возможны только два параметра, тогда иногда нет другого выбора, кроме объединения строк. Нужны мнения по этому вопросу.
7 ответов
Речь идет о производительности конкатенации строк. Это потенциально важно, если у вас плотные записи в журнале.
(До SLF4J 1.7) но возможны только два параметра
Поскольку подавляющее большинство операторов ведения журнала имеют 2 или менее параметров, поэтому API SLF4J до версии 1.6 охватывает (только) большинство случаев использования. Разработчики API предоставляют перегруженные методы с параметрами varargs начиная с версии API 1.7.
В тех случаях, когда вам нужно больше 2, и вы застряли с пре-1.7 SLF4J, просто используйте конкатенацию строк или new Object[] { param1, param2, param3, ... }
, Их должно быть достаточно, чтобы производительность была не такой важной.
Короткая версия: да, это быстрее, с меньшим количеством кода!
Конкатенация строк выполняет большую работу, не зная, нужна ли она или нет (традиционный тест "отладка включена", известная из log4j), и его следует избегать, если это возможно, так как {} позволяет отложить вызов toString() и конструкцию строки после того, как было решено, нужно ли захватывать событие или нет. По моему мнению, если в формате логгера используется одна строка, код становится чище.
Вы можете предоставить любое количество аргументов. Обратите внимание, что если вы используете старую версию sljf4j и у вас есть более двух аргументов {}
, вы должны использовать new Object[]{a,b,c,d}
синтаксис для передачи массива вместо. См., Например, http://slf4j.org/apidocs/org/slf4j/Logger.html.
Что касается скорости: Ceki недавно опубликовал тест в одном из списков.
Поскольку String является неизменяемым в Java, поэтому левая и правая строки должны быть скопированы в новую строку для каждой пары конкатенации. Итак, лучше перейти на заполнитель.
Другая альтернатива String.format()
, Мы используем его в jcabi-log (оболочка статической утилиты вокруг slf4j).
Logger.debug(this, "some variable = %s", value);
Это гораздо более легко обслуживать и расширять. Кроме того, это легко перевести.
Я думаю, с точки зрения автора, основная причина заключается в том, чтобы уменьшить накладные расходы на конкатенацию строк. Я просто прочитал документацию регистратора, вы можете найти следующие слова:
/**
* <p>This form avoids superfluous string concatenation when the logger
* is disabled for the DEBUG level. However, this variant incurs the hidden
* (and relatively small) cost of creating an <code>Object[]</code> before
invoking the method,
* even if this logger is disabled for DEBUG. The variants taking
* {@link #debug(String, Object) one} and {@link #debug(String, Object, Object) two}
* arguments exist solely in order to avoid this hidden cost.</p>
*/
*
* @param format the format string
* @param arguments a list of 3 or more arguments
*/
public void debug(String format, Object... arguments);
Конкатенация стоит дорого, поэтому вы хотите, чтобы это происходило только тогда, когда это необходимо. Используя , slf4j выполняет конкатенацию, только если требуется трассировка. В производственной среде вы можете настроить уровень журнала на INFO, игнорируя таким образом все трассировки отладки.
Подобная трассировка объединит строку, даже если трассировка будет проигнорирована, что является пустой тратой времени:
logger.debug("Temperature set to"+ t + ". Old temperature was " + oldT);
Такая трассировка будет игнорироваться бесплатно:
logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
Если у вас есть много трассировок отладки, которые вы игнорируете в рабочей среде, используя
{}
определенно лучше, так как это не влияет на производительность.
Соответствующее ведение журнала очень важно для разработки приложений, поскольку оно влияет на производительность.
Упомянутое несоответствующее ведение журнала приводит к избыточному вызову метода toString() при каждом вызове и приводит к избыточному выделению временной памяти и обработке ЦП, как можно увидеть в примере выполнения крупномасштабного теста, где мы можем взглянуть на избыточный выделенная временная память:
Посмотрите на профилирование метода:
Примечание. Я являюсь автором этой записи в блоге Ведение журнала о влиянии на производительность приложения .