なぜ僕はCaliperではなくJMHを選んだのか。
今日、会社のblogのほうにJMHのエントリーを書きました。
そう、今日のテーマはマイクロベンチマークです。
Javaのマイクロベンチマークツール「JMH」 - Taste of Tech Topics
Javaのマイクロベンチマークに興味がある人は、
GoogleのCaliperというマイクロベンチマークツールを既にご存知かも知れません。
しかし上記のエントリーではCaliperには全く触れていません。
なぜか。
いや、Caliperを試そうとしたら、うまく動かせなかったんですよ (^^;
そんな、まともに動かせない所や、ドキュメントの更新のないCaliperに幻滅した後
JMHを試してみたら、思いのほか素直で使いやすかったため上で紹介するに至りました。
ちょっとここでは、その辺りの舞台裏を紹介してみます。
Caliperをはじめてみようとしたけど・・・
Caliperのトップページには、Get started的な始め方が記載されています。
http://code.google.com/p/caliper/
Mavenプロジェクトを作って、pom.xmlに追記して、
トップページにあるサンプルソースコードをコピーして・・・
あれ、えっと・・・?
一体、どうやって実行するのでしょう? まさか実行の仕方を調べるためだけに、
30分近いチュートリアルビデオを見なければいけないのでしょうか?
さすがにそれはありえないので、ドキュメントを見てみましょう。
Caliperはドキュメントを更新する気がないのかね。
Google Codeのドキュメントと言えば、Wiki。
https://code.google.com/p/caliper/w/list
早速、このWikiを見てみると・・・あぁ、UsersGuideというのがあるようです。
http://code.google.com/p/caliper/wiki/UsersGuide
何これ、目次だけでまだドキュメントが全然ありません。
QuickStartもないので、始めようがありませんでした。
この点、JMHも同じくドキュメントはほとんどありませんが
少なくともトップページで動かせるまでは面倒を見てくれるので
Caliperよりも親切だと言えます。
Code Samplesのコンパイルが通らない
トップページにあるサンプルだけではきっと動かないのだと思い、
リンクされてる「Very short tutorial examples.」を試してみることにしました。
https://code.google.com/p/caliper/source/browse/tutorial/Tutorial.java
うん、コンパイルが通らない (^^;
少し調べてみると、どうやらCaliperはバージョン1.0から大幅にAPIが変わって
アノテーションベースになるらしく、リンク先のサンプルはそれに合った内容となっています。
しかしいまMavenリポジトリにあるものは、命名規則ベースの古いバージョンで、
setUpやtimeXxxという名前のメソッドを探して実行するという、JUnit3のような思想になっています。
なんかこんな風に、複数のバージョンの情報が混在していて
きちんと情報が整理されていない辺りに、心が折れ始めました。
Caliperを動かしたら、いきなり30秒以上かかって死んだ。
その後もうしばらく調べてみて、どうやらCaliperMainクラスのmainメソッドから
ベンチマークを実行できることが分かりました。
ということで自分で簡単なベンチマークを書いてみたうえで
オプションなどつけずに実行してみました。
順調に進んでるかな・・・
Experiment selection: Instruments: [allocation, micro] User parameters: {} Virtual machines: [default] Selection type: Full cartesian product This selection yields 4 experiments. Starting experiment 1 of 4: {instrument=allocation, method=WithInitialSize, vm=default, parameters={}} Complete! Starting experiment 2 of 4: {instrument=allocation, method=WithoutInitialSize, vm=default, parameters={}} Complete! Starting experiment 3 of 4: {instrument=micro, method=WithInitialSize, vm=default, parameters={}} ERROR: Trial failed to complete (its results will not be included in the run): Trial exceeded the total allowable runtime (30s). The limit may be adjusted using the --time-limit flag.
・・・と思ったら
なんか30秒以上実行したせいでエラーとなりました。
引数を指定すれば30秒制限を突破できるようですが、
そもそも何を何回実行しようとしてエラーになったのか、さっぱり分からないので
30秒制限をオフにして良いのかどうかも分かりません。
だいぶ心が折れてきました。
Caliperでテスト終わったら、勝手に結果がアップロードされた。
先ほどのテストは、まだ続きがあります。
片方は30秒制限を受けましたが、もう一方は何やらきちんと終了したようです。
Starting experiment 4 of 4: {instrument=micro, method=WithoutInitialSize, vm=default, parameters={}} Complete! Execution complete: 1.151m. Collected 45 measurements from: 2 instrument(s) 1 virtual machine(s) 2 benchmark(s) Results have been uploaded. View them at: https://microbenchmarks.appspot.com/runs/d94be1c2-8be0-48e7-8481-4492145eecd5 Process finished with exit code 0
えっと、結果は・・・1分と少々掛かって、えっと・・・
って、何!?
ベンチマークの結果がアップロードされたって?
そうなんです、普通に実行しただけなのに、ベンチマークの結果がGAEにアップロードされました。
恐らくオプションなどを指定してオフライン実行などもできるでしょうし、
こうやってアップロードされることで、より詳しく分析などもできるなど
嬉しいこともたくさんあるのだと思います。
しかしながら、簡単にマイクロベンチマークを取りたいという僕の想いとは
あまりに掛け離れた思想をしているCaliperに愛想がつきて、心は完全に折れました。
それに比べて、JMHは素直です。
まずは @GenerateMicroBenchmark アノテーションさえつければ動きますし、
オプションなど指定しなくともきちんと動き、分かりやすい結果を出してくれます。
少なくともいまこの時点で始めるのであれば、
JMHの方が使いやすいと言えるのではないのかな、と思います。
批判、コメント、アドバイス、どしどしお待ちしています!