O'Reilly Japan - Javaパフォーマンス
こちらの本の2章まとめ
1章 イントロダクション - Qiita ←前回記事
2章 パフォーマンステストのアプローチ - Qiita←今回記事
3章 Javaパフォーマンスのツールボックス - Qiita←次回記事
4章 JIT コンパイラのしくみ - Qiita
5章 ガベージコレクションの基礎 - Qiita
実アプリケーションでテストする
3種類のテストがある
マイクロベンチマーク
名前の通り、小さい単位でテストするもの。
ちょっとした実装の差異を比較するときに使う。
テストコードを書くときは注意が必要で、処理結果を使うようなコードにしないと、コンパイラの最適化により計算処理が削除されてしまう。
マイクロベンチマークが、マルチスレッドかシングルスレッドかに関わらず、volatile
(最適化しない。キャッシュしたくないときにも使われる。)をつけることは重要。
マイクロベンチマークは実運用ではほとんど問題にならない同期がボトルネックになることが多く、その解消に時間を取られるため。
↓volatileについての参考資料
Declaring a Variable Volatile (Writing Device Drivers)
ベンチマークで、複数スレッドからsynchronized
メソッドを呼び出すような場合、同期がボトルネックになってしまうため、ベンチマークというよりは、JVMが競合を解消する時間の計測になってしまうことも注意が必要。
入力値をあらかじめ用意して、それを渡すといった工夫により、ベンチマークのコードに余分な処理をつけないようにする。
正しい入力値に基づいてテストを行うべき。たとえば、実運用ではありえない極端に大きな数字での計測などはしない。
4章で説明されるが、Javaはコードを繰り返し実行されると速くなっていくので、ウォームアップは行うべき。
マクロベンチマーク
アプリケーションのパフォーマンスをテストするためには、使用される外部リソースを組み合わせてテストするのが一番。
このようなテストをマクロベンチマークという。
メゾベンチマーク
実際の処理だが、完全なアプリケーションが使われるわけではないが、マイクロベンチマークよりは粒度の大きいテスト。
例えば、Webサーバーが応答する速度の測定するもの(セッションやログインの機能を試していない)。
メゾベンチマークは自動化テストにも適している。
スループット、バッチ、レスポンスタイムを理解する スループット、バッチ、レスポンスタイムを理解する
バッチ(一括)処理の測定
アプリケーションの開始から終了までを測定するもの。
全体として問題にならない場合は有効。
逆にウォームアップされる前が遅い場合に問題になる場合は別の測定方法が必要。
Javaの場合はウォームアップが必要なので、やや簡単にはできない。
スループットの計測
一定時間内にどれだけ処理が行えるかの計測。
クライアント-サーバー型の場合は、シンクタイム(think time。何も処理を行わずに待つ時間)無しで計測する必要がある。
1秒間当たりのリクエストの数がよく使われる。TPS(transactions per second)、RPS(requests per second)、OPS(operations per second)など。
レスポンスタイムのテスト
レスポンスタイムの算出方法は2つ。
1つは平均値。2つ目はパーセンタイル値。
パーセンタイル値は、例えば90パーセンタイル値1.5秒の場合は、90%のリクエストのレスポンスタイムは1.5秒以下で、残りの10%が1.5 秒以上となる。
本書では、↓のロードジェネレータが紹介されていた
About Faban
不安定性を理解する
テストが時とともに変化する。
優れたベンチマークは実世界に近い実行の度に異なるランダム性を持ったデータを使う。
テスト結果を比較する時、コードに問題があるのか、それとも偶然なのかを判断するのが困難。
ベースライン | 標本 | |
---|---|---|
1回目 | 1.0秒 | 0.5秒 |
2回目 | 0.8秒 | 1.25秒 |
3回目 | 1.2秒 | 0.5秒 |
平均値 | 1.0秒 | 0.75秒 |
というテスト結果の場合、スチューデントのt検定により、43%の確率でパフォーマンスは同じとなる。 |
しかし、データには不確実性があるため、いくら分析を行ったとしても断定的な判断はできない。
早期から頻繁にテストを行う
頻繁にテストを行うのは重要だが、現状とのバランスを見てやる必要がある。
以下に適合するのであれば、早期の頻繁なテストが極めて有益。解決のヒントが得られやすいため。
- すべてを自動化する
- すべてを測定する
- ターゲットのシステム上で実行する