Logger slf4j advantages of formatting with {} instead of string concatenation

OptimizationLoggingConcatenationString FormattingSlf4j

Optimization Problem Overview


Is there any advantage of using {} instead of string concatenation?

An example from slf4j

logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);

instead of

logger.debug("Temperature set to"+ t + ". Old temperature was " + oldT);

I think it's about speed optimization because parameters evaluation (and string concatenation) could be avoided in runtime depending on a config file. But only two parameters are possible, then sometimes there is no other choice than string concatenation. Needing views on this issue.

Optimization Solutions


Solution 1 - Optimization

It is about string concatenation performance. It's potentially significant if your have dense logging statements.

> (Prior to SLF4J 1.7) But only two parameters are possible

Because the vast majority of logging statements have 2 or fewer parameters, so SLF4J API up to version 1.6 covers (only) the majority of use cases. The API designers have provided overloaded methods with varargs parameters since API version 1.7.

For those cases where you need more than 2 and you're stuck with pre-1.7 SLF4J, then just use either string concatenation or new Object[] { param1, param2, param3, ... }. There should be few enough of them that the performance is not as important.

Solution 2 - Optimization

Short version: Yes it is faster, with less code!

String concatenation does a lot of work without knowing if it is needed or not (the traditional "is debugging enabled" test known from log4j), and should be avoided if possible, as the {} allows delaying the toString() call and string construction to after it has been decided if the event needs capturing or not. By having the logger format a single string the code becomes cleaner in my opinion.

You can provide any number of arguments. Note that if you use an old version of sljf4j and you have more than two arguments to {}, you must use the new Object[]{a,b,c,d} syntax to pass an array instead. See e.g. http://slf4j.org/apidocs/org/slf4j/Logger.html#debug(java.lang.String, java.lang.Object[]).

Regarding the speed: Ceki posted a benchmark a while back on one of the lists.

Solution 3 - Optimization

Since, String is immutable in Java, so the left and right String have to be copied into the new String for every pair of concatenation. So, better go for the placeholder.

Solution 4 - Optimization

Another alternative is String.format(). We are using it in jcabi-log (static utility wrapper around slf4j).

Logger.debug(this, "some variable = %s", value);

It's much more maintainable and extendable. Besides, it's easy to translate.

Solution 5 - Optimization

I think from the author's point of view, the main reason is to reduce the overhead for string concatenation.I just read the logger's documentation, you could find following words:

/**
* <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);

Solution 6 - Optimization

Compliant logging is highly important for application development, as it affects performance.

The mentioned non-compliant logging is resulting with redundant toString() method invocation on each call, and is resulting with redundant temporary memory allocation and CPU processing, as can be seen at example high scale test execution, where we can take a look on redundant allocated temporary memory: Memory

Look on method profiling:
Look on method profiling

Note: I am the author of this blog post, Logging impact on application performance.

Solution 7 - Optimization

Concatenation is expensive, so you want it to happen only when needed. By using {}, slf4j performs the concatenation only if the trace is needed. In production, you may configure the log level to INFO, thus ignoring all debug traces.

A trace like this will concatenate the string even if the trace will be ignored, which is a waste of time :

logger.debug("Temperature set to"+ t + ". Old temperature was " + oldT);

A trace like this will be ignored at no cost :

logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);

If you have a lot of debug traces that you ignore in production, using {} is definitely better as it has no impact on performance.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHern&#225;n EcheView Question on Stackoverflow
Solution 1 - OptimizationskaffmanView Answer on Stackoverflow
Solution 2 - OptimizationThorbjørn Ravn AndersenView Answer on Stackoverflow
Solution 3 - OptimizationRabin PanthaView Answer on Stackoverflow
Solution 4 - Optimizationyegor256View Answer on Stackoverflow
Solution 5 - OptimizationTianhao WangView Answer on Stackoverflow
Solution 6 - OptimizationLiranView Answer on Stackoverflow
Solution 7 - OptimizationChristophe QuintardView Answer on Stackoverflow