Java Microbenchmark Harness (JMH)
Use Case
- 想準確知道 Method 需要執行多長時間,以及執行時間和輸入之間的相關性
- 對比 介面 ,以不同條件下實現的吞吐量
- 查看多少百分比的 Request 在多久的時間內完成
Annotation
@BenchmarkMode- 用於
class / method上Throughout: 整體吞吐量,例如1秒內可以執行多少次呼叫,單位ops/timeAverageTime: 每次操作的平均時間,單位time/opSampleTime: 隨機取樣,最後輸出取樣結果的分布SingleShotTime: 只運行一次,同時常常把@Warmup次數設為0,用於測試冷啟動的性能All: 上述所有模式皆執行一次
- 用於
@State- 指定一個物件的作用範圍
Scope.Benchmark: 所有測試Thread共享一個instance,測試有狀態instance在Multi-Thread共享下的性能Scope.Group: 同一個 Thread 在同一個 group 裡共享 instanceScope.Thread: default state, 每個 Test Thread 分配一個 instance
- 指定一個物件的作用範圍
@OutputTimeUnit- 統計結果的時間單位,用於
class / method上
- 統計結果的時間單位,用於
@Warmup- 一般前幾次進行程式測試的時候都會比較慢,需要先預熱幾輪,保證測試正確性
iterations: 預熱次數time: 每次預熱時間timeUnit: default secondbatchSize: 批次處理大小,每次操作呼叫幾次方法
- 一般前幾次進行程式測試的時候都會比較慢,需要先預熱幾輪,保證測試正確性
預熱原因:
JVM 有 JIT 機制,如果某個func()被呼叫多次,JVM 會嘗試將其編譯為 Machine Code,從而提高執行速度,為了讓 benchmark 的結果更加接近真實情況就需要進行預熱。
@Measurement: 實際呼叫Method所需要配置的基本測試參數,可用於class/method,Params與@Warmup相同@Threads: 每個Process中的Test Thread,可用於class/method@Fork: 如果 fork number = 2,則 JMH 會 fork 兩個 Process 來進行測試,可用於class/method@Param: 特別適合用來測試一個func()在不同參數輸入的情況下的性能,只能作用於 字段 上,使用此標註必須定義@State
Result Analyze
Result "com.lex.StringConnectTest.testStringBuilderAdd":
426.954 ±(99.9%) 60.926 ns/op [Average]
(min, avg, max) = (409.871, 426.954, 452.426), stdev = 15.822
CI (99.9%): [366.027, 487.880] (assumes normal distribution)426.954 ±(99.9%) 60.926 ns/op [Average]- 每次操作平均耗時 426.954 ± 60.926 納秒
- 最小值:
409.871 - 平均值:
426.954 - 最大值:
452.426 - 標準差:
15.822 - 平均值的信賴區間:
[366.027, 487.880]
Benchmark (length) Mode Cnt Score Error Units
StringConnectTest.testStringAdd 10 avgt 5 133.950 ± 3.264 ns/op
StringConnectTest.testStringAdd 50 avgt 5 1121.863 ± 55.314 ns/op
StringConnectTest.testStringAdd 100 avgt 5 3544.262 ± 199.877 ns/op
StringConnectTest.testStringBuilderAdd 10 avgt 5 46.597 ± 3.005 ns/op
StringConnectTest.testStringBuilderAdd 50 avgt 5 217.872 ± 11.888 ns/op
StringConnectTest.testStringBuilderAdd 100 avgt 5 426.954 ± 60.926 ns/oplength:@ParamvalueMode:@BenchmarkMode哪一種模式Cnt:@Measurement()運行次數Score:- If benchmark mode is
Throughput, then a higher score indicates better performance, because it measures the number of operations that can be executed per unit of time (e.g. operations per second). - If the benchmark mode is
AverageTime, then a lower score indicates better performance, because it measures the time taken for a single operation to execute (e.g. nanoseconds per operation).
- If benchmark mode is
Error: 誤差,信心區間Units: 每次呼叫單位時間