java – 为什么StringBuilder链接模式sb.append(x).append(y)比常规sb.append(x)更快; sb.append(Y)?

我有一个微基准测试,显示非常奇怪的结果:

@BenchmarkMode(Mode.Throughput)
@Fork(1)
@State(Scope.Thread)
@Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000)
@Measurement(iterations = 40, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000)
public class Chaining {

    private String a1 = "111111111111111111111111";
    private String a2 = "222222222222222222222222";
    private String a3 = "333333333333333333333333";

    @Benchmark
    public String typicalChaining() {
        return new StringBuilder().append(a1).append(a2).append(a3).toString();
    }

    @Benchmark
    public String noChaining() {
        StringBuilder sb = new StringBuilder();
        sb.append(a1);
        sb.append(a2);
        sb.append(a3);
        return sb.toString();
    }
}

我期待两个测试的结果相同或至少非常接近.但是,差异几乎是5倍:

# Run complete. Total time: 00:01:41

Benchmark                  Mode  Cnt      Score     Error  Units
Chaining.noChaining       thrpt   40   8538.236 ± 209.924  ops/s
Chaining.typicalChaining  thrpt   40  36729.523 ± 988.936  ops/s

有谁知道这怎么可能?

最佳答案
字符串连接a b c是Java程序中非常频繁的模式,因此HotSpot JVM对它有一个特殊的优化:-XX:OptimizeStringConcat默认为ON.

HotSpot JVM在字节码中识别新的StringBuilder().append()… append().toString()模式,并将其转换为优化的机器代码,而无需调用实际的Java方法,也无需分配中间对象.即这是一种复合JVM内在的.

这是优化的source code.

另一方面,sb.append(); sb.append(); ……没有特别处理.此序列的编译方式与常规Java方法调用类似.

如果使用-XX:-OptimizeStringConcat重新运行基准测试,则两种变体的性能将相同.

转载注明原文:java – 为什么StringBuilder链接模式sb.append(x).append(y)比常规sb.append(x)更快; sb.append(Y)? - 代码日志