JDK-8076758 : new StringBuilder().append(String).toString() should be recognized by OptimizeStringConcat
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-04-03
  • Updated: 2015-11-09
  • Resolved: 2015-09-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b82Fixed
Related Reports
Relates :  
Description
There is a corner case in String optimizations that is missing. It's a questionable programming practice, since the code sequence should just be replaced by "new String(s)", or even "s" assuming the new identity is not required. However, it might be trivial to support in OptimizeStringConcat?

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(3)
public class ConcatSimpleBench {

    @Param({"1", "64", "4096"})
    int size;

    private String s;

    @Setup
    public void setup() {
        s = "";
        for (int c = 0; c < size; c++) {
            s += "a";
        }
    }

    @Benchmark
    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
    public String base() {
        return new String(s);
    }

    @Benchmark
    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
    public String sb() {
        return new StringBuilder().append(s).toString();
    }
}

Yields:

Benchmark               (size)  Mode  Cnt    Score    Error  Units
ConcatSimpleBench.base       1  avgt   15    4.971 ��  0.992  ns/op
ConcatSimpleBench.base      64  avgt   15    4.972 ��  1.044  ns/op
ConcatSimpleBench.base    4096  avgt   15    5.249 ��  1.045  ns/op
ConcatSimpleBench.sb         1  avgt   15   11.267 ��  2.628  ns/op
ConcatSimpleBench.sb        64  avgt   15   16.219 ��  0.296  ns/op
ConcatSimpleBench.sb      4096  avgt   15  814.078 �� 12.745  ns/op

"base" tests experiences constant-time performance (the char[] array is just shared). "sb" test experiences close to O(n), since it copies the backing char[] storage.
Comments
This issue becomes important for Indify String Concat (JDK-8085796) work, that may routinely produce expressions like this, as the intermediate computation.
27-08-2015

Proof-of-concept patch that solves the issue in a benchmark: http://cr.openjdk.java.net/~shade/8076758/webrev.00/ I'm not entirely sure it works in a face of deoptimization.
27-08-2015

Benchmark: http://cr.openjdk.java.net/~shade/8076758/ConcatSimpleBench.java Executable JAR: http://cr.openjdk.java.net/~shade/8076758/benchmarks.jar
03-04-2015