【问题标题】:Why is String concatenation faster than String.valueOf for converting an Integer to a String?为什么字符串连接比 String.valueOf 将 Integer 转换为 String 更快?
【发布时间】:2017-06-30 20:12:58
【问题描述】:

我有一个基准:

@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 有什么魔力?

【问题讨论】:

  • "" + 100 对于编译器来说可能更清楚地识别为常量......
  • 其中之一是方法调用。另一个,编译器可以随心所欲地编译。
  • @LouisWasserman 它未编译为常量。编译为StringBuider()构造。
  • JIT 通常不会在较小的运行中发挥作用。你给了基准什么样的热身?
  • 我同意这里的情况似乎并非如此。由于我在上面链接到的讨论,一般情况下不一定如此,在未来的编译器版本中也不一定如此。

标签: java performance microbenchmark


【解决方案1】:

正如您所提到的,HotSpot JVM 具有 -XX:+OptimizeStringConcat 优化,可识别 StringBuilder 模式并将其替换为高度调整的手写 IR 图,而 String.valueOf() 依赖于一般编译器优化。

通过分析生成的汇编代码,我发现了以下主要区别:

  • 优化的 concat 不会为结果字符串创建 char[] 数组,而 Integer.toString 创建的数组在分配后会像任何其他常规对象一样被清除。
  • 优化的 concat 通过简单的 addition of '0' constant 将数字转换为字符,而 Integer.getChars 使用 table lookup 以及相关的数组边界检查等。

PhaseStringOpts::int_getCharsInteger.getChars 的实现还有其他细微差别,但我想它们对性能的影响并不大。


顺便说一句,如果您采用更大的数字(例如 1234567890),性能差异将可以忽略不计,因为 Integer.getChars 中的 extra loop 一次转换两位数。

【讨论】:

    猜你喜欢
    • 2021-04-18
    • 2020-12-18
    • 2011-11-10
    • 1970-01-01
    • 2015-07-22
    • 2012-02-16
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多