Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How much does Java optimize string concatenation with +?

I know that in more recent Java versions string concatenation

String test = one + "two"+ three;

Will get optimized to use a StringBuilder.

However will a new StringBuilder be generated each time it hits this line or will a single Thread Local StringBuilder be generated that is then used for all string concatenation?

In other words can I improve on the performance for a frequently called method by creating my own thread local StringBuilder to re-use or will there be no significant gains by doing so?

I can just write a test for this but I wonder if it might be compiler/JVM specific or something that can be answered more generally?

like image 372
Tim B Avatar asked Oct 26 '16 16:10

Tim B


1 Answers

As far as I know, there is no compiler generating code reusing StringBuilder instances, most notably javac and ECJ don’t generate reusing code.

It’s important to emphasize that it is reasonable not to do such re-use. It’s not safe to assume that code retrieving an instance from a ThreadLocal variable is faster than a plain allocation from a TLAB. Even by trying to add the potential costs of a local gc cycle for reclaiming that instance, as far as we can identify its fraction on the costs, we can’t conclude that.

So the code trying to reuse the builder would be more complicated, wasting memory, as it keeps the builder alive without knowing whether it ever will be actually reused, without a clear performance benefit.

Especially when we consider that additionally to the statement above

  • JVMs like HotSpot have Escape Analysis, which can elide pure local allocations like these altogether and also may elide the copying costs of array resize operations
  • Such sophisticated JVMs usually also have optimizations dedicated specifically to StringBuilder based concatenation, which work best when the compiled code follows the common pattern

With Java 9, the picture is going to change again. Then, string concatenation will get compiled to an invokedynamic instruction which will get linked to a JRE provided factory at runtime (see StringConcatFactory). Then, the JRE will decide how the code will look like, which allows to tailor it to the specific JVM, including buffer re-use, if it has a benefit on that particular JVM. This will also reduce the code size, as it requires only a single instruction rather than the sequence of an allocation and multiple calls into the StringBuilder.

like image 96
Holger Avatar answered Oct 03 '22 21:10

Holger