为什么将整数转换为字符串时,字符串连接比 String.valueOf 更快?
Why is String concatenation faster than String.valueOf for converting an Integer to a String?
我有一个基准:
@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
有什么魔力?
正如您所提到的,HotSpot JVM 具有 -XX:+OptimizeStringConcat
优化,可以识别 StringBuilder 模式并将其替换为高度调整的 hand-written IR 图,而 String.valueOf()
依赖于一般编译器优化。
通过分析生成的汇编代码,我发现了以下主要区别:
- 优化的 concat 不会将
char[]
为结果字符串创建的数组归零,而 Integer.toString
创建的数组在分配后会像任何其他常规对象一样被清除。
- 优化的 concat 通过简单 addition of '0' constant, while
Integer.getChars
uses table lookup 和相关的数组边界检查等将数字转换为字符
PhaseStringOpts::int_getChars
vs. Integer.getChars
的实现还有其他细微差别,但我想它们对性能影响不大。
顺便说一句,如果你取一个更大的数字(例如 1234567890),性能差异可以忽略不计,因为 Integer.getChars
中的 extra loop 一次转换两位数。
我有一个基准:
@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
有什么魔力?
正如您所提到的,HotSpot JVM 具有 -XX:+OptimizeStringConcat
优化,可以识别 StringBuilder 模式并将其替换为高度调整的 hand-written IR 图,而 String.valueOf()
依赖于一般编译器优化。
通过分析生成的汇编代码,我发现了以下主要区别:
- 优化的 concat 不会将
char[]
为结果字符串创建的数组归零,而Integer.toString
创建的数组在分配后会像任何其他常规对象一样被清除。 - 优化的 concat 通过简单 addition of '0' constant, while
Integer.getChars
uses table lookup 和相关的数组边界检查等将数字转换为字符
PhaseStringOpts::int_getChars
vs. Integer.getChars
的实现还有其他细微差别,但我想它们对性能影响不大。
顺便说一句,如果你取一个更大的数字(例如 1234567890),性能差异可以忽略不计,因为 Integer.getChars
中的 extra loop 一次转换两位数。