[Java] G1 and Flight Recorder's -XX:FlightRecorderOptions=stackdepth option

原文はこちら。
https://blogs.oracle.com/poonam/entry/g1_and_flight_recorder_s

先頃。お客様から次のような報告がありました。
G1GCで -XX:FlightRecorderOptions=stackdepth=512 を指定し JFR (Java Flight Recorder) を使うとパフォーマンスの劣化が見られた。しかしstackdepth (スタックの深さ) の設定は同じで同じ設定でParallel GCの場合にはパフォーマンスに影響はなかった。
このフライト・レコーディングの結果、低パフォーマンスの原因はJFRCheckpointという操作によって生じる停止であることがわかりました。この JFRCheckpoint による停止は -XX:FlightRecorderOptions=stackdepth=512 を指定して記録を開始する場合においてのみ発生し、 -XX:FlightRecorderOptions=stackdepth=3 を指定した場合には発生しませんでした。
考えられる理由を調べてみましょう。The time taken by the JFRCheckpoint 操作の所要時間は、ディスクに書き出すために必要なデータの量に直に比例します。G1GCでは、TLAB (Thread Local Allocation Buffer) のサイズが小さいため、実質的に数多くの 'Allocation in TLAB' イベントと 'Allocation outside TLAB' イベントが生成されます。スタックの深さをstackdepthオプションで増やすと、G1GCでは他のGCに比べてずっと多くのスタックトレースデータをディスクに書き込む必要があります。
簡単なテストを実行することにしました。GCが頻繁に発生するアプリケーションをまず、Parallel GCで実行し、その後G1 GCで実行しました。これらの両方のテストでは、HotSpot Defaultの記録を開始し、その後プロファイル設定を使って手作業で時間を修正した記録を開始しました。その結果以下のことがわかりました。
  1. G1GCの場合、GCイベントの個数はParallel GCに比べて遙かに多い。
  2. TLABはG1では小さいため、Parallel GCの場合に比べてより多くのアロケーション・イベントが発生する。
  3. 両GCでの2分間のプロファイル記録で生成されたファイルのサイズを比較すると、G1 GCでは約3MBなのに対し、Parallel GCでは約600KBだった。これは示しているG1 GCでディスクに書き込むデータ量がParallel GCの場合に比べて大きいことを示している、この結果、JFRCheckpointによる長時間の停止が発生する原因になっている。
まとめると、G1GCでJFRを使っている場合、stackdepthで指定するスタックの深さはデフォルト値(デフォルトは64)を使う。もしくはJFRCheckpointオペレーションの長時間の停止が見られる場合には、ずっと小さな値をstackdepthに指定して実行することを推奨します。

0 件のコメント:

コメントを投稿