これは何?
これはJava Advent Calendar 2016 - Qiitaの9日目の記事です。
8日目の記事はcero_tさんのOptimizing JavaというJavaパフォーマンス系の書籍が面白そう でした。
10日目は @sh-ogawa さんです。
最初に
Javaでプログラムを書くとき、そのロジックのパフォーマンスについて思いをはせたことはありますか?
コーディングルールや、先輩の教えをそのまま鵜呑みにして書いていませんか?
例えば、文字列の結合はStringBuilderを使えと教わり、何の疑いもなくそのまま書いていませんか?
先輩の教えは尊いものです。無下にしてはいけません。
しかしながら、その教えは実は古いバージョンでは有効だったが、最新バージョンでは古い知識だったということもあるかもしれません。
または、重たい処理ロジックを書いてしまったけど、金の弾丸で解決すればいいや、と思っていませんか?
普段のコーディングではあまりパフォーマンスを意識しないかもしれませんが、この記事を読んでいる間だけでも、ちょっとだけ意識してみませんか?
パフォーマンス測定について
処理したい範囲をSystem.currentTimeMillis();で囲んで、差を引き算するというやり方をよく見かけます。
果たして、それは正しい測定方法なのでしょうか。
プログラム全体の処理速度を測るのであれば、そのやり方でも問題ないと思います。
しかし、プログラムの中の、何回も、何百回も、何万回も呼ばれる特定のメソッドの処理速度を測定する時はちょっとだけ再考していただきたいのです。
パフォーマンス測定の話が出ると、必ずウォームアップという言葉が出てきます。
これについては、Javaの理論と実践: 動的コンパイルとパフォーマンス測定 等を参照してください。
では、どうすればいいのでしょうか。
手助けの一つとして、OpenJDK: jmhというOpenJDKが開発しているツールがあります。
簡単な紹介
JJUG CCC 2016 fail で20分お話しました。
そのときのスライドを参照してください。
JMH超入門 - Docs.com
IDEでの動かし方について
Mavenが使えればいいので、eclipse、NetBeans、 IntelliJ IDEA のどれでも動きます。
※OpenJDKのページの、Related projectsのところにIntelliJ IDEA JMH Pluginがあるのですが、使い方がよくわかりませんでした。使いこなせた方、教えてください。
サンプルソース等
JMH Samples
この中にあるコードを一通り触ると、大体の感触はつかめると思います。
私の過去のJMHに関する投稿
導入及び、動かし方メモ
- Javaのベンチマークツール、JMHの導入 - Qiita
- Javaのベンチマークツール、JMHにテストコードを書いて計測してみる - Qiita
- Javaのベンチマークツール、JMHをコマンドラインから実行するときのメモ - Qiita
実際に測定してみた例
JMHをどこで使うか
趣味としての使い道
今後、Qiitaや、自分のブログでパフォーマンス測定結果を載せる時は System.currentTimeMillis(); で囲んだ結果ではなく、JMHを使ってみませんか?
業務での使い道
メインとなるプログラムの中で、JMHを使うことはほぼないと思います。
別のサンプルプログラムを書き、その中にテストしたいメソッドをコピーして実行するという使い方が主になるのではないでしょうか。
私が現在関わっている業務では、JMHを組み込めていないので自分の業務ではこのような使い方をしている、というのがあれば教えてください。
ライブラリーのテストの場合は、テスト対象のメソッドを作り、この中からライブラリーの目的となるクラス、メソッドを呼び出す形での測定が最もやりやすいと思います。
心がけたいこと
先輩の教えは尊いものです。過去の経験則からのアドバイスもあると思います。
ですが、1から10まで鵜呑みにするのではなく、気になったことは自分で検証しましょう。
そして、検証した結果、先輩の教えと違う結果が出た場合はその旨、先輩に報告してどうすべきか真剣に考えましょう。
パフォーマンスは向上していても、可読性がとても下がった、メンテナンスが難しいコードになってしまっては意味がありません。
可読性を優先すべきこともあるかと思います。
JMHでのテスト結果のみを以て、自分の考えを貫き通すことだけは止めましょう。