tokuhirom's blog

Java mixed-mode flame graphsについてのメモ

http://www.brendangregg.com/blog/2015-11-06/java-mixed-mode-flame-graphs.html

Java mixed-mode flame graphs ってエントリがどんな問題を解決しているか

  • perf を用いた軽量なプロファイリングを java でも
    • perf-map-agent を利用することで java のメソッドもプロファイリング可能
    • Java のプロファイリングと kernel/libc などの system profiling をいっぺんにできる
    • この2つのものを同時にプロファイリングできることを mixed-mode といっているようだ
  • flame graphs で見やすいグラフを
    • NYTProf とかで出てる奴ね

といった問題を解決しているのだが、解決している問題が多岐に渡っていて理解しにくい。

必要な環境

  • jdk8u60+
  • linux
  • perf

とりあえず試す

sudo yum install -y perf

で perf を install

sudo yum install -y java-1.8.0-openjdk-devel

openjdk なら -devel パッケージもインストールしないと perf-map-agent をビルドできない(oraclejdk でどうなのかは未検証)。

perf のメトリクス取るのの基本

sudo perf record -F 99 -ag -- sleep 30 で、99Hz で 30 sec のプロファイリング。

sudo perf report -f でレポートを curses で見れる

perf-map-agent を使う

https://github.com/jrudolph/perf-map-agent

[tokuhirom@develop perf-map-agent]$ git clone https://github.com/jrudolph/perf-map-agent.git                                                                                                        
Cloning into 'perf-map-agent'...
remote: Counting objects: 336, done.
remote: Total 336 (delta 0), reused 0 (delta 0), pack-reused 336
Receiving objects: 100% (336/336), 95.16 KiB | 0 bytes/s, done.
Resolving deltas: 100% (165/165), done.
[tokuhirom@develop perf-map-agent]$ cmake .
-- Found JNI: /usr/lib/jvm/jre/lib/amd64/libjawt.so  
-- JNI_INCLUDE_DIRS=/usr/lib/jvm/java/include;/usr/lib/jvm/java/include/linux;/usr/lib/jvm/java/include
-- JNI_LIBRARIES=/usr/lib/jvm/jre/lib/amd64/libjawt.so;/usr/lib/jvm/jre/lib/amd64/server/libjvm.so
-- JAVA_INCLUDE_PATH=/usr/lib/jvm/java/include
-- JAVA_INCLUDE_PATH2=/usr/lib/jvm/java/include/linux
-- Found Java: /bin/java (found version "1.8.0.91") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/tokuhirom/perf-map-agent

perf-map-agent というコマンドラインツールを用意する。これが特定の PID の java process に attach して、JVM TI (JVM Tool Inteface) で情報を集めて perf 用の形式で出力してくれる。このツールを利用するには -XX:+PreserveFramePointer をターゲットの jvm の起動時につける必要がある(このオプションは java 8u60+ で利用可能)。

create-java-perf-map.sh

./bin/perf-java-top

localdev-provisioning%20%E2%80%94%20tokuhirom@develop:~%20%E2%80%94%20ssh%20%E2%97%82%20vagrant%20ssh%20and%20blog%20admin

net.virtualvoid.perf.AttachOnce 実行して map を取得したあと、perf top している。↑↑のスクショを見ると、java method の情報も取得できていることがわかる。

まとめ

  • perf-map-agent 便利
    • 得に、Atlassian など導入しているときにボトルネックさっくり知りたいとかそういうケースでは恩恵がおおきそう
    • あるいは norikra とか
  • 通常の web app の場合、適用範囲は限定的かもしれない
    • しかし、perf ほど気軽に使えるものもあんまないのでこの方法は有りかもしれない
  • perf-map-agent はjvmti を利用するCコードをターゲットVMにねじ込む
    • バグがあるとこれ起因でクラッシュするかもしれない
Created: 2016-05-08 14:37:03 +0000
Updated: 2016-05-09 03:38:10 +0000