StringBuilder improves memory consumption and performance for multiple additions. Lets analyze next example (imagine that javac doesn't optimize any String concatenations):
String s = "a" + "b" + "c" + "d" + ... + "z";
StringBuilder sb = new StringBuilder("a").append("b").append("c")....append("z");
In case of String concatenation with + java will add strings from left to right, creating a new string each time: "ab", then "abc", then "abcd", thus 25 new strings, and each time it will copy the previous result completely. While StringBuilder will simply add each string to its own char[] array, without any redundant objects creation.
Now let n be the number of strings, and l - the length of each string. In this case the complexity of the mth + will be O(l*m), because each time the whole previous strings concatenation is copied. Thus we can make a conclusion that summary time (and memory (!)) complexity will be O(l*n*n) for String case. While in the case of StringBuilder it will be O(l*n).
Also regarding logging - small performance comparison:
@Benchmark
public void stringConcatenation(Blackhole bh) {
// By using all these string we should prevent string builder optimizations.
String a = "start ";
String b = a + "first";
String c = b + " inside ";
String d = c + "second";
String e = d + ", ";
String f = e + 1024;
bh.consume(a);
bh.consume(b);
bh.consume(c);
bh.consume(d);
bh.consume(e);
bh.consume(f);
}
@Benchmark
public void stringBuilder(Blackhole bh) {
StringBuilder sb = new StringBuilder("start ")
.append("first")
.append(" inside ")
.append("second")
.append(", ")
.append(1024);
bh.consume(sb.toString());
}
@Benchmark
public void logback(Blackhole bh) {
// Logback formatting
bh.consume(MessageFormatter.arrayFormat("start {} inside {}, {}", new Object[]{"first", "second", 1024}).getMessage());
}
@Benchmark
public void log4j(Blackhole bh) {
// Log4j formatting
bh.consume(messageFactory.newMessage("start {} inside {}, {}", "first", "second", 1024));
}
And the results:
Benchmark Mode Cnt Score Error Units
LogBenchmark.stringConcatenation thrpt 5 9080147,269 ? 988134,269 ops/s
LogBenchmark.stringBuilder thrpt 5 27136050,849 ? 2776464,863 ops/s
LogBenchmark.logback thrpt 5 3579746,331 ? 346554,072 ops/s
LogBenchmark.log4j thrpt 5 4992342,169 ? 335971,537 ops/s
So as you can see suggested by some guys "use logging framework formatter instead" may not be the better choice if you are actually logging a lot.