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() при каждом вызове и приводит к избыточному выделению временной памяти и обработке ЦП, как можно увидеть в примере выполнения крупномасштабного теста, где мы можем взглянуть на избыточный выделенная временная память:Память

Посмотрите на профилирование метода:
Посмотрите на профилирование методов

Примечание. Я являюсь автором этой записи в блоге Ведение журнала о влиянии на производительность приложения .

Другие вопросы по тегам