私はJHMを初めて使用します。テストするために、次の簡単な方法を書きました
@Benchmark
@OutputTimeUnit(TimeUnit.SECONDS)
public long sumPar(){
return
LongStream.rangeClosed(1, LIMIT)
.parallel()
.sum();
}
テストの結果は大きく変わりました
# JMH 1.10.3 (released 8 days ago)
# VM version: JDK 1.8.0_45, VM 25.45-b02
# VM invoker: /usr/lib/jvm/java-8-oracle/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: testStreams.Bench.sumPar
# Run progress: 22.21% complete, ETA 00:02:33
# Fork: 1 of 1
# Warmup Iteration 1: 53.495 ops/s
# Warmup Iteration 2: 57.971 ops/s
# Warmup Iteration 3: 57.622 ops/s
# Warmup Iteration 4: 58.113 ops/s
# Warmup Iteration 5: 57.861 ops/s
Iteration 1: 50.414 ops/s
Iteration 2: 9.207 ops/s
Iteration 3: 9.176 ops/s
Iteration 4: 9.212 ops/s
Iteration 5: 9.175 ops/s
複数回実行した後も同じ動作が観察されました。ウォームアップの反復を減らした後でも、5/6 の反復の後でも ops/s の低下が見られました。並列操作を使用したテスト スイートのその他のベンチマークは、一貫して実行されました。
私は JMH を初めて使用します。いくつか質問があります。
- 分散を少なくするために調整できる JMH の構成パラメーターはありますか?
- これは、問題のメソッドを複数回繰り返したときに予想される動作ですか?
- JHM が正しく報告している場合、このメソッドをデバッグして、ops/s がドロップする理由を見つけるにはどうすればよいですか?
いくつかの仕様
intel i7-4810MQ @ 2.80GHz
16GB RAM
Ubuntu 14.04 running on virtual box on windows host
virtual machine is alloacted 3 CPU cores
JDK 1.8.0_45
JMH 1.10.3
編集
すべてのフィードバックに感謝します。
今朝、ラップトップの電源を一晩中オフにして、ベンチマークを再実行しました。一貫性のない動作は完全になくなりました。反復を 1000 に増やしても、ops/s は一貫したままでした。
CPU 温度を確認すると、84 度で安定していました。
この問題を再現できませんでした。次に CPU が過熱していると思われる場合は、このベンチマークを再実行し、CPU 温度を監視して、この動作が再発するかどうかを確認したいと思います。
実行時に使用すると、 Arrays.stream().map().sum() の不安定なパフォーマンスの-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining
メソッドと同様のコンパイルパターンが示されましたが、それがこの問題の根本的な原因ではないと思います。
編集2
-XX:MaxInlineLevel=12
フラグ追加で再現、解決できました。
DevBox:~/test$ java -jar target/benchmarks.jar testStreams.Bench -i 5 -wi 5 -f 1
# JMH 1.10.3 (released 8 days ago)
# VM version: JDK 1.8.0_45, VM 25.45-b02
# VM invoker: /usr/lib/jvm/java-8-oracle/jre/bin/java
# VM options: <none>
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: testStreams.Bench.sumPar
# Run progress: 0.00% complete, ETA 00:00:30
# Fork: 1 of 1
# Warmup Iteration 1: 53.672 ops/s
# Warmup Iteration 2: 57.720 ops/s
# Warmup Iteration 3: 58.320 ops/s
# Warmup Iteration 4: 58.174 ops/s
# Warmup Iteration 5: 58.680 ops/s
Iteration 1: 49.810 ops/s
Iteration 2: 9.109 ops/s
Iteration 3: 9.427 ops/s
Iteration 4: 9.437 ops/s
Iteration 5: 9.436 ops/s
DevBox:~/test$ java -XX:MaxInlineLevel=12 -jar target/benchmarks.jar testStreams.Bench -i 1000 -wi 5 -f 1
# JMH 1.10.3 (released 8 days ago)
# VM version: JDK 1.8.0_45, VM 25.45-b02
# VM invoker: /usr/lib/jvm/java-8-oracle/jre/bin/java
# VM options: -XX:MaxInlineLevel=12
# Warmup: 5 iterations, 1 s each
# Measurement: 1000 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: testStreams.Bench.sumPar
# Run progress: 0.00% complete, ETA 00:50:16
# Fork: 1 of 1
# Warmup Iteration 1: 53.888 ops/s
# Warmup Iteration 2: 58.328 ops/s
# Warmup Iteration 3: 58.468 ops/s
# Warmup Iteration 4: 58.455 ops/s
# Warmup Iteration 5: 57.937 ops/s
Iteration 1: 58.717 ops/s
Iteration 2: 59.494 ops/s
Iteration 3: 60.013 ops/s
Iteration 4: 59.506 ops/s
Iteration 5: 51.543 ops/s
-XX:MaxInlineLevel=12
以前に省略されたときに問題を再現できなかった理由について、根本的な原因をまだ見つけていません。私が見る限り、同じ設定を使用していました。ラップトップをしばらくアイドル状態にしてから、もう一度ベンチマークを実行してみるかもしれませんが、今のところ、JIT インライン化についての洞察を得られたことに満足しています。