为什么 StringBuilder 链接模式 sb.append(x).append(y) 比常规 sb.append(x) 更快; sb.append(y)?
Why is the StringBuilder chaining pattern sb.append(x).append(y) faster than regular 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 识别字节码中的 new StringBuilder().append()...append().toString()
模式并将其转换为优化的机器代码,而无需调用实际的 Java 方法,也无需分配中间对象。 IE。这是一种复合 JVM 内在。
这是此优化的 source code。
另一方面,sb.append(); sb.append(); ...
没有特别处理。这个序列的编译就像一个常规的 Java 方法调用。
如果您使用 -XX:-OptimizeStringConcat
重新运行基准测试,两种变体的性能将相同。
我有一个显示非常奇怪结果的微基准测试:
@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 识别字节码中的 new StringBuilder().append()...append().toString()
模式并将其转换为优化的机器代码,而无需调用实际的 Java 方法,也无需分配中间对象。 IE。这是一种复合 JVM 内在。
这是此优化的 source code。
另一方面,sb.append(); sb.append(); ...
没有特别处理。这个序列的编译就像一个常规的 Java 方法调用。
如果您使用 -XX:-OptimizeStringConcat
重新运行基准测试,两种变体的性能将相同。