async-profilerのガイド
1. 概要
Javaサンプリングプロファイラーは通常、JVMツールインターフェイス(JVMTI)を使用して設計され、セーフポイントでスタックトレースを収集します。 したがって、これらのサンプリングプロファイラーはセーフポイントバイアス問題の影響を受ける可能性があります。
アプリケーションの全体像を把握するには、スレッドがセーフポイントにある必要がなく、セーフポイントバイアスの問題を回避するためにいつでもスタックトレースを収集できるサンプリングプロファイラーが必要です。
このチュートリアルでは、 async-profiler と、それが提供するさまざまなプロファイリング手法について説明します。
2. 非同期プロファイラー
async-profiler は、 HotSpotJVMに基づく任意のJDKのサンプリングプロファイラーです。 オーバーヘッドが低く、JVMTIに依存しません。
HotSpotJVMが提供するAsyncGetCallTrace APIを使用してJavaコードパスをプロファイリングし、Linuxの perf_events を使用してネイティブコードパスをプロファイリングすることにより、セーフポイントバイアスの問題を回避します。
つまり、プロファイラーはJavaコードとネイティブコードパスの両方のコールスタックを照合して、正確な結果を生成します。
3. 設定
3.1. インストール
まず、プラットフォームに基づいたasync-profilerの最新リリースをダウンロードします。 現在、LinuxおよびmacOSプラットフォームのみをサポートしています。
ダウンロードしたら、プラットフォームで動作しているかどうかを確認できます。
$ ./profiler.sh --version
Async-profiler 1.7.1 built on May 14 2020
Copyright 2016-2020 Andrei Pangin
async-profilerで利用可能なすべてのオプションを事前に確認することをお勧めします。
$ ./profiler.sh
Usage: ./profiler.sh [action] [options]
Actions:
start start profiling and return immediately
resume resume profiling without resetting collected data
stop stop profiling
check check if the specified profiling event is available
status print profiling status
list list profiling events supported by the target JVM
collect collect profile for the specified period of time
and then stop (default action)
Options:
-e event profiling event: cpu|alloc|lock|cache-misses etc.
-d duration run profiling for seconds
-f filename dump output to
-i interval sampling interval in nanoseconds
-j jstackdepth maximum Java stack depth
-b bufsize frame buffer size
-t profile different threads separately
-s simple class names instead of FQN
-g print method signatures
-a annotate Java method names
-o fmt output format: summary|traces|flat|collapsed|svg|tree|jfr
-I include output only stack traces containing the specified pattern
-X exclude exclude stack traces with the specified pattern
-v, --version display version string
--title string SVG title
--width px SVG width
--height px SVG frame height
--minwidth px skip frames smaller than px
--reverse generate stack-reversed FlameGraph / Call tree
--all-kernel only include kernel-mode events
--all-user only include user-mode events
--cstack mode how to traverse C stack: fp|lbr|no
is a numeric process ID of the target JVM
or 'jps' keyword to find running JVM automatically
示されているオプションの多くは、後のセクションで役立ちます。
3.2. カーネル構成
Linuxプラットフォームでasync-profilerを使用する場合は、すべてのユーザーがperf_eventsを使用してコールスタックをキャプチャするようにカーネルを構成する必要があります。
まず、 perf_event_paranoid を1に設定します。これにより、プロファイラーはパフォーマンス情報を収集できます。
$ sudo sh -c 'echo 1 >/proc/sys/kernel/perf_event_paranoid'
次に、 kptr_restrict を0に設定して、カーネルアドレスの公開に関する制限を削除します。
$ sudo sh -c 'echo 0 >/proc/sys/kernel/kptr_restrict'
ただし、async-profilerはmacOSプラットフォームで単独で動作します。
プラットフォームの準備ができたので、プロファイリングアプリケーションを構築し、Javaコマンドを使用して実行できます。
$ java -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -jar path-to-jar-file
ここでは、正確な結果を得るために強く推奨される-XX:+ UnlockDiagnosticVMOptions -XX:+DebugNonSafepointsJVMフラグを使用してプロファイリングアプリを開始しました。
アプリケーションのプロファイリングの準備ができたので、async-profilerでサポートされているさまざまなタイプのプロファイリングについて見ていきましょう。
4. CPUプロファイリング
Async-profiler は、CPUのプロファイリング時に、JVMコード、ネイティブクラス、カーネル関数など、Javaメソッドのサンプルスタックトレースを収集します。
PIDを使用してアプリケーションのプロファイルを作成しましょう。
$ ./profiler.sh -e cpu -d 30 -o summary 66959
Started [cpu] profiling
--- Execution profile ---
Total samples : 28
Frame buffer usage : 0.069%
ここでは、 -e オプションを使用して、cpuプロファイリングイベントを定義しました。 次に、 -d
最後に、 -oオプションは、サマリー、HTML、トレース、SVG、ツリーなどの出力形式を定義するのに役立ちます。
アプリケーションのCPUプロファイリング中にHTML出力を作成しましょう。
$ ./profiler.sh -e cpu -d 30 -f cpu_profile.html 66959
ここでは、HTML出力を使用して、サンプルを展開、折りたたみ、および検索できることがわかります。
さらに、 async-profilerは、すぐに使用できるフレームグラフをサポートします。
アプリケーションのCPUプロファイルに.svgファイル拡張子を使用して、フレームグラフを生成してみましょう。
$ ./profiler.sh -e cpu -d 30 -f cpu_profile.svg 66959
ここで、結果のフレームグラフは、Javaコードパスを緑色、C ++を黄色、システムコードパスを赤色で示しています。
5. 割り当てプロファイリング
同様に、バイトコードインストルメンテーションのような煩わしい手法を使用せずに、メモリ割り当てのサンプルを収集できます。
async-profiler は、 TLAB (スレッドローカル割り当てバッファー)ベースのサンプリング手法を使用して、TLABの平均サイズを超えるヒープ割り当てのサンプルを収集します。
alloc イベントを使用することで、プロファイラーがプロファイリングアプリケーションのヒープ割り当てを収集できるようになります。
$ ./profiler.sh -e alloc -d 30 -f alloc_profile.svg 66255
ここでは、オブジェクトのクローン作成によってメモリの大部分が割り当てられていることがわかります。これがなければ、コードを見るときに認識しにくいものです。
6. 壁掛け時計のプロファイリング
また、 async-profiler は、壁掛け時計のプロファイルを使用して、実行中、スリープ中、ブロック中などのステータスに関係なく、すべてのスレッドをサンプリングできます。
これは、アプリケーションの起動時に問題をトラブルシューティングするときに便利です。
wall イベントを定義することにより、すべてのスレッドのサンプルを収集するようにプロファイラーを構成できます。
$ ./profiler.sh -e wall -t -d 30 -f wall_clock_profile.svg 66959
ここでは、 -t オプションを使用して、スレッドごとのモードで壁掛け時計プロファイラーを使用しました。これは、すべてのスレッドをプロファイリングするときに強くお勧めします。
さらに、 list オプションを使用して、JVMでサポートされているすべてのプロファイリングイベントを確認できます。
$ ./profiler.sh list 66959
Basic events:
cpu
alloc
lock
wall
itimer
Java method calls:
ClassName.methodName
7. async-profiler IntelliJIDEAを使用
IntelliJ IDEAは、Javaのプロファイリングツールとしてasync-profilerとの統合を特徴としています。
7.1. プロファイラーの構成
IntelliJIDEAでasync-profilerを構成するには、
]で JavaProfilerメニューオプションを選択します。また、すばやく使用できるように、IntelliJIDEAが提供するCPUプロファイラーや割り当てプロファイラーなどの事前定義された構成を選択できます。
同様に、プロファイラーテンプレートをコピーして、特定のユースケースに合わせてエージェントオプションを編集できます。
7.2. IntelliJIDEAを使用したプロファイルアプリケーション
プロファイラーを使用してアプリケーションを分析する方法はいくつかあります。
たとえば、アプリケーションを選択して選択できます走る
または、ツールバーをクリックして、 走る
または、 プロファイラーで実行下のオプション走るメニューをクリックし、<を選択しますプロファイラー構成名> :
さらに、実行メニューの下にプロファイラーをプロセスに接続するオプションが表示されます。 添付するプロセスを選択できるダイアログが開きます。
アプリケーションのプロファイリングが完了したら、IDEの下部にあるProfilerツールウィンドウバーを使用してプロファイリング結果を分析できます。
アプリケーションのプロファイリング結果は次のようになります。
フレームグラフ、呼び出しツリー、メソッドリストなどのさまざまな出力形式でスレッドごとの結果が表示されます。
または、
8. 結論
この記事では、 async-profiler と、いくつかのプロファイリング手法について説明しました。
最初に、Linuxプラットフォームを使用するときにカーネルを構成する方法と、正確な結果を得るためにアプリケーションのプロファイリングを開始するためのいくつかの推奨されるJVMフラグについて説明しました。
次に、CPU、割り当て、壁掛け時計など、さまざまなタイプのプロファイリング手法を検討しました。
最後に、IntelliJIDEAを使用してasync-profilerでアプリケーションのプロファイリングを行いました。