JMH初体验
什么是JMH
JMH是 Java Microbenchmark Harness 的縮寫。中文意思大致是 “JAVA 微基準測試套件”。
基準測試是指通過設計科學的測試方法、測試工具和測試系統,實現對一類測試對象的某項性能指標進行定量的和可對比的測試。——百度百科
為什么要使用 JMH
基準測試的特質有如下幾種:
可見要做一次符合特質的基準測試,是很繁瑣也很困難的。外界因素很容易影響到最終的測試結果。特別對于 JAVA的基準測試。
有些人認為Java是C++編寫的,一般來說Java編寫的程序不太可能比 C++編寫的代碼運行效率更好。但是Java在某些場景的確要比 C++運行的更高效。不要覺得天方夜譚。其實JVM隨著這些年的發展,已經變得很先進,它會在運行期間不斷的去優化。
這對于我們程序來說是好事,但是對于性能測試就頭疼的。你運行的次數與時間不同可能獲得的結果也不同,很難獲得一個比較穩定的結果。對于這種情況,有一個解決辦法就是大量的重復調用,并且在真正測試前還要進行一定的預熱,使結果盡可能的準確。
如何使用 JMH
導入依賴
新建一個Maven工程,導入依賴:
<!-- Java Microbenchmark Harness --> <dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.19</version> </dependency> <dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.19</version> </dependency>基準測試代碼
package com.lun.string;import org.openjdk.jmh.annotations.Benchmark;public class StringConnectBenchmark {/*** 字符串拼接之 StringBuilder 基準測試*/@Benchmarkpublic void testStringBuilder() {print(new StringBuilder().append(1).append(2).append(3).toString());}/*** 字符串拼接之直接相加基準測試*/@Benchmarkpublic void testStringAdd() {print(new String()+ 1 + 2 + 3);}/*** 字符串拼接之String Concat基準測試*/@Benchmarkpublic void testStringConcat() {print(new String().concat("1").concat("2").concat("3"));}/*** 字符串拼接之 StringBuffer 基準測試*/@Benchmarkpublic void testStringBuffer() {print(new StringBuffer().append(1).append(2).append(3).toString());}/*** 字符串拼接之 StringFormat 基準測試*/@Benchmarkpublic void testStringFormat(){print(String.format("%s%s%s", 1, 2, 3));}public void print(String str) {} }運行基準測試代碼
package com.lun.string;import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder;public class StringBuilderRunner {public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder()// 導入要測試的類.include(StringConnectBenchmark.class.getSimpleName())// 預熱5輪.warmupIterations(5)// 度量10輪.measurementIterations(10).mode(Mode.Throughput).forks(3).build();new Runner(opt).run();} }運行結果
... # Run progress: 93.33% complete, ETA 00:00:17 # Fork: 3 of 3 # Warmup Iteration 1: 168644.227 ops/s # Warmup Iteration 2: 406543.452 ops/s # Warmup Iteration 3: 417524.283 ops/s # Warmup Iteration 4: 453008.474 ops/s # Warmup Iteration 5: 450343.882 ops/s Iteration 1: 452407.964 ops/s Iteration 2: 454286.433 ops/s Iteration 3: 446131.016 ops/s Iteration 4: 449042.238 ops/s Iteration 5: 457997.034 ops/s Iteration 6: 450785.925 ops/s Iteration 7: 450866.167 ops/s Iteration 8: 439266.876 ops/s Iteration 9: 453702.384 ops/s Iteration 10: 451028.848 ops/sResult "com.lun.string.StringConnectBenchmark.testStringFormat":441747.293 ±(99.9%) 15980.806 ops/s [Average](min, avg, max) = (342074.817, 441747.293, 463951.126), stdev = 23919.319CI (99.9%): [425766.487, 457728.099] (assumes normal distribution)# Run complete. Total time: 00:04:23Benchmark Mode Cnt Score Error Units StringConnectBenchmark.testStringAdd thrpt 30 11809268.588 ± 766758.418 ops/s StringConnectBenchmark.testStringBuffer thrpt 30 68501244.128 ± 1373528.962 ops/s StringConnectBenchmark.testStringBuilder thrpt 30 49564682.559 ± 7821622.523 ops/s StringConnectBenchmark.testStringConcat thrpt 30 14246208.232 ± 443906.557 ops/s StringConnectBenchmark.testStringFormat thrpt 30 441747.293 ± 15980.806 ops/sScore分數越高越好
參考資料
總結
- 上一篇: 面试--Linux命令总结
- 下一篇: c++基础学习(12)--(多线程、We