Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

プレゼン、ボランティアコーチします!

勉強会でスピーカーをやりたいけど、プレゼンが初めて、苦手という方に無償でコーチします!資料レビューや録画リハへアドバイスします。Twitter@jyukutyoまでメンションでもDMでも。

私はデブサミやJJUG CCCなど200人規模で登壇経験ありです。海外での登壇も短いながらあり。デブサミ2017では公募スピーカー1位でした!

JITWatchでJITコンパイルを見よう!

この記事は JVM Advent Calendar 4日目 の記事です。

JVM Advent Calendar 2014 - Qiita

JITWatchについて

JVMなみなさんは、JITコンパイルをご存知だと思います。

JITWatchは、アプリケーションにおけるJITコンパイルについて、可視化し分析するためのツールです。

GitHubで公開されており、すぐに使うことができます。ライセンスはBSDなので、とくに問題ありません。

AdoptOpenJDK/jitwatch · GitHub

JITWatchで見るための設定

JITWatchで可視化、分析するためには、アプリケーションでログを出力する必要があります。そのためにJVM引数に次のものを追加します。

-XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+LogCompilation

こうすることで、アプリケーションを実行すると、実行したディレクトリに「hotspot_pid9999.log」(9999は起動したプロセスのIDとなる)というファイルが出力されます。

マシンコードも見る

さらに、JITコンパイラによって生成されたマシンコードを見たい場合、次のオプションも合わせて記述します。

-XX:+PrintAssembly

そしてHSDIS(HotSpot disAssembler)をセットアップします。

HSDISは以下のサイトからダウンロードできます。

Basic Disassembler Plugin for HotSpot: Downloads — Project Kenai

Macの場合、「bsd-libhsdis-i386.dylib」をダウンロードし、「hsdis-amd64.dylib」にリネームします。 JDK8の場合、そのファイルを「JAVA_HOME/jre/lib/server/」に配置してください。

なお、HSDISはデフォルトではAT&Tシンタックスとなります。Intelシンタックスにすることもできるようです(詳細は不明)。

JITWatchの使い方

GitHubからcloneし、mvn packageします。targetディレクトリにjitwatch-1.0.0-SNAPSHOT.jarができます。

なお、ログファイルを簡単に生成したい場合、JITWatchがサンプルアプリを用意してくれているのでそれを利用するとよいです。makeDemoLogFile.shを実行するだけで、ログファイルを生成します。ここからは、そのサンプルが作ったログファイルを使って説明します。

JITWatchのルートディレクトリにlaunchUI.sh(.bat)があるのでそれを実行します。次のようなウィンドウが表示されます。

f:id:jyukutyo:20141204201758p:plain

あとはOpen Logで先ほど出力するようにした「hotspot_pid9999.log」を指定します。次にJITWatch ConfigurationでSource locationsにJDKのsrc.zipとアプリケーションのsrcディレクトリを、Class locationsにはアプリケーションのclassファイルの場所を指定します。

f:id:jyukutyo:20141204201802p:plain

Startボタンを押すとログファイルの解析を開始します。終了すると、次のような画面になります。

f:id:jyukutyo:20141204201806p:plain

ChartやStats、Histo、TopList、Code Cache、TriView、Suggestを押すと、詳細な情報を見ることができます。 これらの画面で出てくるC1やC2という単語はコンパイラレベルです。OSRはOn-Stack replacementのことで、ループ内の最適化のことを指します。

JITWatchで一番おもしろい部分はTriViewです。この画面でソースコードバイトコードアセンブリコードを対比させて見ることができます。

f:id:jyukutyo:20141204201809p:plain

メソッド内の該当コードにポインタを合わせると、その部分のバイトコードアセンブリコードに色がつきます。もしPrintAssemblyしていないときは、アセンブリコードは表示されません。

さらにこの画面でView Compile Chainを押すと、コンパイルのチェーンを見れます。

f:id:jyukutyo:20141204201813p:plain

おもしろい機能はSuggestです。

f:id:jyukutyo:20141204201816p:plain

たとえば以下のようなことが書かれています。

The call at bytecode 3 to
Class: org.adoptopenjdk.jitwatch.demo.MakeHotSpotLog
Member: private long bigMethod(long,int)
was not inlined for reason: 'hot method too big'
The callee method is 'hot' but is too big to be inlined into the caller.
You may want to consider refactoring the callee into smaller methods.
Invocations: 20000
Size of callee bytecode: 350

ホットなメソッドだけれども、メソッドが大きすぎてインライン化できないとあります。リファクタリングしてより小さいメソッドにしようという提案があります。

こういった提案を利用して、よりJITコンパイルを促進するようにアプリケーションを作成することができます。

最後に注意

JITコンパイルには静的なルールと動的なルールがあります。サンプル程度の場合、静的なルールだけが使われますが、実際の環境では動的なルールがほとんどを占めます。ある場合のJITコンパイルのルールが他のアプリケーションでも常に適用できるわけではないので、注意しましょう。

さあ

JITWatchでみんなもHotSpotのJITコンパイルを楽しもう!!

参考

Java Magazine 2014 September October ※閲覧には登録が必要です

Java Magazine - November/December 2014