JMH难题:StringBuilder与StringBand

伊格

我很难理解此基准测试的情况。与相比,我想衡量我的样本课程的StringBand工作方式StringBuilder的想法StringBand是将字符串连接到toString(),而不是append()

资料来源

这是StringBand来源-删除了基准:

public class StringBandSimple {

private String[] array;
private int index;
private int length;

public StringBandSimple(int initialCapacity) {
    array = new String[initialCapacity];
}

public StringBandSimple append(String s) {
    if (s == null) {
        s = StringPool.NULL;
    }
    if (index >= array.length) {
        //expandCapacity();
    }
    array[index++] = s;
    length += s.length();
    return this;
}

public String toString() {
    if (index == 0) {
        return StringPool.EMPTY;
    }

    char[] destination = new char[length];
    int start = 0;
    for (int i = 0; i < index; i++) {
        String s = array[i];
        int len = s.length();
        //char[] chars = UnsafeUtil.getChars(s);
        //System.arraycopy(chars, 0, destination, start, len);
        s.getChars(0, len, destination, start);
        start += len;
    }
    return new String(destination);
}
}

此代码使用:UnsafeUtil.getChars()实际获取Stringchar []而不进行复制,请参见此处的代码我们也可以使用getChars()和它仍然相同。

这是JMH测试:

@State
public class StringBandBenchmark {

String string1;
String string2;

@Setup
public void prepare() {
    int len = 20;
    string1 = RandomStringUtil.randomAlphaNumeric(len);
    string2 = RandomStringUtil.randomAlphaNumeric(len);
}

@GenerateMicroBenchmark
public String stringBuilder2() {
    return new StringBuilder(string1).append(string2).toString();
}

@GenerateMicroBenchmark
public String stringBand2() {
    return new StringBandSimple(2).append(string1).append(string2).toString();
}

}

分析

这是我对添加两个20个字符的字符串时发生的情况的理解。

StringBuilder

  • new char[20+16] 已创建(36个字符)
  • arraycopy被要求将20个string1字符复制StringBuilder
  • 在第二次追加之前,先StringBuilder扩展容量,因为40> 36
  • 因此,new char[36*2+2]被创建
  • arraycopy 20个字符到新缓冲区
  • arraycopy 追加20个字符 string2
  • 最后,toString()回报new String(buffer, 0, 40)

弦带

  • new String[2] 被建造
  • 都追加只是将字符串保留在内部缓冲区中,直到toString()被调用
  • length 增加两次
  • new char[40] 已创建(结果字符串的总长度)
  • arraycopy20个第一个字符串字符(UnsafeUtil提供字符串的实际char[]缓冲区)
  • arraycopy 20秒字符串
  • 最后,回报 new String(buffer, 0, 40)

期望

随着StringBand我们有:

  • 一少arraycopy-这样做的全部目的是什么
  • 分配规模较小:new String[]new char[]vs. 2new char[]
  • 而且我们没有很多检查StringBuilder方法,例如尺寸等

因此,我希望它的StringBand运行速度至少与相同StringBuilder,甚至更快。

基准结果

我在MacBookPro上运行基准测试,2013年中。使用JMH v0.2和Java 1.7b45

命令:

java -jar build/libs/microbenchmarks.jar .*StringBand.* -wi 2 -i 10 -f 2 -t 2

预热迭代次数(2)很好,因为我可以看到第二次迭代达到了相同的性能。

Benchmark                                    Mode Thr     Count  Sec         Mean   Mean error    Units
j.b.s.StringBandBenchmark.stringBand2       thrpt   2        20    1    37806.993      174.637   ops/ms
j.b.s.StringBandBenchmark.stringBuilder2    thrpt   2        20    1    76507.744      582.131   ops/ms

结果说StringBuilder快了两倍。当我将线程数增加到16,或BlackHole在代码中显式使用s时,也会发生同样的情况

为什么?

亚历山大·希普列夫(Aleksey Shipilev)

好吧,像往常一样,“猫头鹰不是它们看起来的样子”。通过快速检查Java代码对代码性能进行推理变得很奇怪。通过查看字节码进行推理的感觉是相同的。即使在极少数情况下汇编太高级而无法解释这种现象,生成的代码反汇编也应对此有所启发。

这是因为平台在每个级别都对代码进行了优化。这是您应该看的提示。在i5 2.0 GHz,Linux x86_64,JDK 7u40上运行基准测试。

基线:

Benchmark                                    Mode Thr     Count  Sec         Mean   Mean error    Units
j.b.s.StringBandBenchmark.stringBand2       thrpt   2        20    1    25800.465      297.737   ops/ms
j.b.s.StringBandBenchmark.stringBuilder2    thrpt   2        20    1    55552.936      876.021   ops/ms

是的,令人惊讶。现在,观看此。我的袖子什么都没有,除了...

-XX:-OptimizeStringConcat:

Benchmark                                    Mode Thr     Count  Sec         Mean   Mean error    Units
j.b.s.StringBandBenchmark.stringBand2       thrpt   2        20    1    25727.363      207.979   ops/ms
j.b.s.StringBandBenchmark.stringBuilder2    thrpt   2        20    1    17233.953      219.510   ops/ms

如原始分析所示,从字符串优化中禁止虚拟机产生“预期”结果。众所周知,HotSpot具有针对StringBuilders的优化,可以有效地识别常见的用法,new StringBuilder().append(...).append(...).toString()并为语句生成更有效的代码。

拆卸和弄清楚应用字符串优化后到底发生了什么,留给有兴趣的读者练习:)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章