Dmi*_*kiy 18 java performance 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 StringConcatTest {
    private int aInt;
    @Setup
    public void prepare() {
        aInt = 100;
    }
    @Benchmark
    public String emptyStringInt() {
        return "" + aInt;
    }
    @Benchmark
    public String valueOfInt() {
        return String.valueOf(aInt);
    }
}
这是结果:
Benchmark                                          Mode  Cnt      Score      Error  Units
StringConcatTest.emptyStringInt                   thrpt   40  66045.741 ± 1306.280  ops/s
StringConcatTest.valueOfInt                       thrpt   40  43947.708 ± 1140.078  ops/s
它表明将空字符串与整数相连接比调用String.value(100)快30%.我明白""+ 100转换为
new StringBuilder().append(100).toString()
并且-XX:+OptimizeStringConcat应用优化以使其快速.我不明白的是为什么valueOf它本身比连接慢.有人可以解释究竟发生了什么以及为什么""+ 100更快.有什么神奇之处OptimizeStringConcat?
apa*_*gin 14
正如您所提到的,HotSpot JVM具有-XX:+OptimizeStringConcat可识别StringBuilder模式的优化,并将其替换为高度调整的手写IR图,同时String.valueOf()依赖于通用编译器优化.
通过分析生成的汇编代码,我发现了以下关键差异:
char[]为结果字符串创建零数组,而创建的数组Integer.toString在分配后就像任何其他常规对象一样被清除.Integer.getChars使用表查找与相关的数组边界检查等.PhaseStringOpts::int_getCharsvs 的实现还有其他细微差别Integer.getChars,但我猜它们对性能没有那么重要.
顺便说一句,如果你把一个更大的数字(如1234567890),性能差异可以忽略不计,因为的额外的循环中Integer.getChars,在一次两位数字的转换.