为什么StringBuilder的链式模式sb.append(x).append(y)比普通的sb.append(x)更快; sb.append(Y)?
我有一个显示非常奇怪的结果的microbenchmark:
@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(); } }
我期待两个testing的结果是相同的,或者至less非常接近。 然而,差异几乎是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
有人知道这有可能吗?
string连接a + b + c
是Java程序中非常频繁的模式,所以HotSpot JVM对其进行了特殊的优化: -XX:+OptimizeStringConcat
默认为ON。
HotSpot JVM在字节码中识别new StringBuilder().append()...append().toString()
模式,并将其转换为优化的机器代码,而无需调用实际的Java方法,也不需要分配中间对象。 即这是一种复合JVM本质。
这里是这个优化的源代码 。
另一方面, sb.append(); sb.append(); ...
sb.append(); sb.append(); ...
没有专门处理 这个序列就像普通的Java方法调用一样编译。
如果您使用-XX:-OptimizeStringConcat
重新运行基准testing,则两种变体的性能将保持不变。