使用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非常聪明,可能会优化成运行时常量,测试毫无意义;
尽量减少不必要的操作,比如动态生成字符串,要提前创建好
以下是测试用例:
测试结果如下:
总结一下:
String.format虽然有着更好的可读性,但性能远远不及其它方式,在性能敏感的场景应该谨慎使用;
StringBuilder是最快的;
String加法和StringBuilder性能差别不大,具体可能与编译器的优化有关系;
placeholderFomat性能不差,且有着不错的可读性
另,贴上placeholderFomat源码:
字符串加法: “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(); }
相关文章推荐
- 使用开源的Profiler来测试你的Java应用程序的性能
- 使用开源的Profiler来测试你的Java应用程序的性能
- java字符串拼接与性能
- JAVA的字符串拼接与性能
- Java 5种字符串拼接方式性能比较。 .
- Java 5种字符串拼接方式性能比较。
- 使用开源的Profiler来测试你的Java应用程序的性能
- JAVA的字符串拼接与性能
- 使用JMeter进行性能测试 —“Java请求”方式
- 使用JMeter进行性能测试(Java请求)
- 使用loadrunner Java Vuser协议进行性能测试时场景中报Error: Compilation process failed.解决方法
- 使用开源的Profiler来测试你的Java应用程序的性能
- JAVA的字符串拼接与性能
- Java 5种字符串拼接方式性能比较。
- JAVA的字符串拼接与性能
- JAVA的字符串拼接与性能
- 使用开源的Profiler来测试你的Java应用程序的性能
- 使用javap分析你的程序性能(以字符串拼接为例)
- 使用开源的Profiler来测试你的Java应用程序的性能
- JAVA的字符串拼接与性能