JMH难题:StringBuilder与StringBand

 旺仔牛叉糖 发布于 2023-02-11 12:31

我很难理解这个基准测试的进展情况.我想测量我的样本类的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)

StringBand

new String[2] 被建造

两者都只是将字符串保留在内部缓冲区中,直到toString()被调用

length 增加两次

new char[40] 已创建(结果字符串的总长度)

arraycopy20个第一个字符串字符(UnsafeUtil提供字符串的实际char[]缓冲区)

arraycopy 20秒的字符串字符

最后,回归 new String(buffer, 0, 40)

期望

随着StringBand我们:

少一点arraycopy- 这样做的目的是什么

减少分配规模:new String[]new char[]两个new char[]

加上我们没有像StringBuilder方法那样的很多检查(对于大小等)

所以我希望它StringBand至少可以起作用StringBuilder,如果不是更快的话.

基准测试结果

我在2013年中期在MacBookPro上运行基准测试.使用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时,也会发生同样的情况.

为什么?

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有