Javaのカレンダー | Advent Calendar 2021の3日目の記事です
概要
Javaの単体テストのベンチマーク(性能測定)を簡単に取りたいときに使える方法
golang の go test -bench
のようにサクッとメソッドの性能を確認したいときに利用します
参考
やり方
pom.xml
dependencies に以下を追加
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.33</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.33</version>
<scope>provided</scope>
</dependency>
測定コード
ポイント
-
@Test で JMH の Runner を初期化します
- 初期化で設定するのはデフォルト値だと余分な forks と warmup iterations のみを変更
- 測定したいテストメソッドに @Benchmark をつける
public class BenchmarkTest {
// Junit の Test アノテーションで Runner を設定する
@Test
void benchMark() throws RunnerException {
Options opt = new OptionsBuilder()
.include(BenchmarkTest.class.getSimpleName())
.forks(1) // 1回実行
.warmupIterations(1) // 1回繰り返し
.build();
new Runner(opt).run();
}
// 測定したいテストに Benchmark アノテーションをつける
@Benchmark
public void test() throws InterruptedException {
match(new Date().toString());
}
// テスト対象のメソッド(中身は適当)
static boolean match(String str) {
final var pattern = Pattern.compile(".*1*2");
return pattern.matcher(str).find();
}
}
実行結果
Benchmark Mode Cnt Score Error Units
BenchmarkTest.test thrpt 5 4242841.831 ± 189193.259 ops/s
応用
試してはいませんが、以下は考慮ポイントです
- 個別に設定を変えたい場合は、Runner の設定値をいじるのではなく、アノテーション(@BenchmarkMode, @Fork, @State)でベンチマークテストごとに設定を変える
- ものによってはテストモードを Mode.AverageTime (平均時間)にしたほうがわかりやすいかもしれない
- ただし、測定対象のメソッドが速すぎると、平均時間が目視で確認できなくなるので注意
- コンパイルの最適化で速くなるケースがあるので、コンパイラの気持ちになって書く