您的位置:首页 > 编程语言 > Java开发

使用JMH(Java Microbenchmark Harness)测试Java字符串拼接性能

2017-07-26 00:00 441 查看
最近由于项目需要,需要比较各种情况下进行字符串拼接的性能。主要的字符串拼接方法有下面四种:

字符串加法: “Hello” + "Word";

StringBuilder: new StringBuilder("Hello").append("World");

调用String.format模板方法: String.format("%s%s","Hello","World");

笔者自己编写的slf4j风格的PlaceholderFormat: FastStringUtils.placeholderFomat("{}{}","Hello","World")

JMH是openJDK JIT小组研发的微基准测试框架,结果还是比较可靠的。

但是,在编写测试用例的时候,有几点需要注意:

不要在测试方法内部创建循环,框架本身会多次调用;

不要对常量进行字符串加减操作来测试性能,JIT非常聪明,可能会优化成运行时常量,测试毫无意义;

尽量减少不必要的操作,比如动态生成字符串,要提前创建好

以下是测试用例:

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3)
@Measurement(iterations = 7)
public class StringFormatTest {

private static final int SIZE = 0x4ff;

private int index = 0;

private final String[] a = new String[SIZE];
private final String[] b = new String[SIZE];
private final String[] c = new String[SIZE];

@Setup
public void setup() {
Random random = new Random();
for (int i = 0; i < SIZE; i++) {
a[i] = random.nextInt() + "";
b[i] = random.nextLong() + "";
c[i] = random.nextDouble() + "";
}
}

@Benchmark
public String testStringFormat() {
if (++index >= SIZE)
index = 0;
return String.format("%s:%s:%s", a[index], b[index], c[index]);
}

@Benchmark
public String testStringAdd() {
if (++index >= SIZE)
index = 0;
return a[index] + ':' + b[index] + ':' + c[index];
}

@Benchmark
public String testStringBuilder() {
if (++index >= SIZE)
index = 0;
return new StringBuilder(a[index])
.append(':')
.append(b[index])
.append(':')
.append(c[index])
.toString();
}

@Benchmark
public String testPlaceholderFormat() {
if (++index >= SIZE)
index = 0;
return FastStringUtils.placeholderFormat("{}:{}:{}", a[index], b[index], c[index]);
}

}

测试结果如下:

Benchmark                               Mode  Cnt     Score    Error  Units
StringFormatTest.testPlaceholderFormat  avgt   70   130.732 ±  2.519  ns/op
StringFormatTest.testStringAdd          avgt   70   102.576 ±  1.368  ns/op
StringFormatTest.testStringBuilder      avgt   70    94.908 ±  1.097  ns/op
StringFormatTest.testStringFormat       avgt   70  1156.455 ± 16.516  ns/op

总结一下:

String.format虽然有着更好的可读性,但性能远远不及其它方式,在性能敏感的场景应该谨慎使用;

StringBuilder是最快的;

String加法和StringBuilder性能差别不大,具体可能与编译器的优化有关系;

placeholderFomat性能不差,且有着不错的可读性

另,贴上placeholderFomat源码:

public static String placeholderFormat(String s, Object... args) {
int len1 = s.length(), len2 = args.length;
StringBuilder builder = new StringBuilder();
int i = 0, j = 0;
while (i < len1) {
char c = s.charAt(i);
if (c == '{') {
if (s.charAt(i + 1) == '}' && j < len2) {
builder.append(args[j++]);
i += 2;
continue;
} else {
builder.append('{');
}
} else {
builder.append(c);
}
i++;
}
return builder.toString();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息