[optimization] Logger slf4j advantages of formatting with {} instead of string concatenation

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.

The answer is


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.


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.


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.


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.


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

Examples related to optimization

Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly? Measuring execution time of a function in C++ GROUP BY having MAX date How to efficiently remove duplicates from an array without using Set Storing JSON in database vs. having a new column for each key Read file As String How to write a large buffer into a binary file in C++, fast? Is optimisation level -O3 dangerous in g++? Why is processing a sorted array faster than processing an unsorted array? MySQL my.cnf performance tuning recommendations

Examples related to logging

How to redirect docker container logs to a single file? Console logging for react? Hide strange unwanted Xcode logs Where are logs located? Retrieve last 100 lines logs Spring Boot - How to log all requests and responses with exceptions in single place? How do I get logs from all pods of a Kubernetes replication controller? Where is the Docker daemon log? How to log SQL statements in Spring Boot? How to do logging in React Native?

Examples related to concatenation

Pandas Merging 101 What does ${} (dollar sign and curly braces) mean in a string in Javascript? Concatenate two NumPy arrays vertically Import multiple csv files into pandas and concatenate into one DataFrame How to concatenate columns in a Postgres SELECT? Concatenate string with field value in MySQL Most efficient way to concatenate strings in JavaScript? How to force a line break on a Javascript concatenated string? How to concatenate two IEnumerable<T> into a new IEnumerable<T>? How to concat two ArrayLists?

Examples related to string-formatting

JavaScript Chart.js - Custom data formatting to display on tooltip Format in kotlin string templates Converting Float to Dollars and Cents Chart.js - Formatting Y axis String.Format not work in TypeScript Use StringFormat to add a string to a WPF XAML binding How to format number of decimal places in wpf using style/template? How to left align a fixed width string? Convert Java Date to UTC String Format a Go string without printing?

Examples related to slf4j

Where does the slf4j log file get saved? Building with Lombok's @Slf4j and Intellij: Cannot find symbol log How to configure slf4j-simple SLF4J: Class path contains multiple SLF4J bindings SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". in a Maven Project SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". error java.lang.ClassNotFoundException: org.apache.log4j.Level Logger slf4j advantages of formatting with {} instead of string concatenation ClassNotFoundException: org.slf4j.LoggerFactory Configuring Log4j Loggers Programmatically