JVMのGC 実践ガイド 後編(分析カタログと診断フロー)

パフォーマンスチューニング
スポンサーリンク
google.com, pub-5238665064291805, DIRECT, f08c47fec0942fa0

1. はじめに

本記事は、JVMにおけるGC(ガーベジコレクション)の観測と分析に焦点を当てた「後編」です。
チューニングには踏み込まず、取得した観測データ(jstat出力など)をどのように読み解くかについて説明していきます。


2. 診断フロー(まずはこれを確認)

[開始]
  ↓
[FGC > 0 ?]──Yes──>【重大】原因特定を最優先
                    (Old逼迫 / Metaspace / 断片化 / System.gc())
  │No
  ↓
[YGCの周期は安定?]──No──> Eden小 or 割当過多(Young過多)を疑う
  │Yes
  ↓
[Old(O%)は高止まり?]──Yes──> 昇格過多/巨大配列/キャッシュの疑い(Mixed効率も確認)
  │No
  ↓
[Metaspace(M/CCS)は高い?]──Yes──> クラスロード過多/リークを点検
  │No
  ↓
[GCT/稼働% は許容内?]──No──> YoungGC頻度や並行フェーズ負荷を再点検
  │Yes
  ↓
【現状維持】(観測継続・履歴比較)
  • 判断材料は中編で扱ったjstatの列(E/O/M/CCS/YGC/FGC/YGCT/FGCT/GCT)。
  • ZGCの注意:FGCは基本0のまま。ZGCではポーズ指標(YGCT/GCTの増え方)アプリ指標(p99レイテンシ/CPU)を合わせて評価。

3. 指標のしきい値(観測のみの目安)

指標目安補足
FGC0回1回でも発生原因の特定価値あり
GCT/稼働時間< 5%Web/API一般目安。用途/SLAで調整
Old (O%) ピーク< 80%連続ピーク/単調増は要注意
E (Eden%)Young直前で高→直後に下がる周期の安定を重視
M/CCS高止まりしない動的クラス生成/再ロード頻発に注意

※しきい値は「出発点」。自分のベースラインを持ち、差分で異常を検知するのが実務的。


4. 代表パターン・カタログ

※ 例では -t指定時のTimestamp列を前提(TimeではなくTimestampになります)

4.1 安定(G1)

Timestamp  S0 S1   E   O   M  CCS   YGC  YGCT   FGC  FGCT   GCT
      0.0   0  0  12  40  15   10     0 0.000     0 0.000  0.000
     10.0   4  0  93  42  16   10     3 0.090     0 0.000  0.090
     20.0   1  5  18  41  16   10     4 0.120     0 0.000  0.120

読み: Young周期は10秒前後で安定。Oldは滑らか、FGC=0、GCT は小さい → 健全。


4.2 Young 過多(Eden 小 / 割当過多)

Timestamp   E   O   YGC  YGCT   GCT
       0.0  10  35     0 0.000  0.000
       1.0  95  36     3 0.060  0.060
       2.0  93  37     6 0.120  0.120

読み: 1 秒ごとにYoung。割当レートがEdenに対し高い。周期を伸ばせるかを分析対象に。


4.3 Old張り付き(Mixedが効かない)

Timestamp   E   O  YGC FGC  GCT
       0.0  10  70    0   0 0.000
      30.0  90  85   12   0 0.200
      60.0  88  88   24   1 0.600

読み: Old が80%近辺で高止まり → ついにFGC昇格過多/巨大配列/キャッシュを疑う(Mixed の効きも弱い)。


4.4 Metaspace高止まり

Timestamp   M  CCS   FGC  FGCT
       0.0  40  18     0  0.000
      30.0  85  45     0  0.000
      60.0  92  48     1  0.300

読み: M/CCS の伸びが止まらず、ついにFGC動的クラス生成/プラグイン/再ロードを点検。
(例:テンプレート/バイトコード生成系、熱リロード、OSGi/プラグイン等)


4.5 ZGC の読み方の例(低ポーズ型の観測)

Timestamp   YGC  YGCT   FGC  FGCT   GCT
       0.0     0 0.000     0 0.000  0.000
      30.0     1 0.002     0 0.000  0.002
      60.0     2 0.004     0 0.000  0.004
Timestamp   YGC  YGCT   FGC  FGCT   GCT
       0.0     0 0.000     0 0.000  0.000
      30.0     1 0.002     0 0.000  0.002
      60.0     2 0.004     0 0.000  0.004

読み: 回数/累積停止時間が小さく出る。レイテンシは良好だがCPU負荷は別途監視(低ポーズの代償で並行処理が多い)。
※ ZGCではE/O/S0/S1の列はG1のようには解釈しない停止時間とアプリ指標の相関で評価。


5. 計算式

  • 割当速度(MB/s) ≒(Young直後→次Young直前EU増分)÷ Young間隔(秒)÷ 1024(KB→MB換算)
  • 昇格速度(MB/s) ≒(Young直前/直後のOU増分)÷ Young間隔(秒) ÷ 1024
  • 平均Youngポーズ(ms/回)ΔYGCT / ΔYGC × 1000(区間内でYoungが複数回なら平均)
  • 区間のGC割合(%)ΔGCT / ΔTimestamp × 100(観測ウィンドウ内のGCオーバーヘッド)

※いずれも差分(Δ)を取るのがコツ(累積値をそのまま単発で割らない)。


6. 分析メモの例

### 観測条件
- 期間: 2025-08-22 10:00–10:30 (JST)
- 負荷: 60rps、90%読取 / 10%書込
- JVM: Java21, G1GC, -Xms2g -Xmx2g
- 採取: jstat -gcutil -t -h10 <pid> 5000 360

### 概要
FGC=0、Young周期≈12s、Oldピーク61%、GCT/稼働0.4% → 影響軽微。

### 事実(jstat要約)
- YGC=126(YGCT=7.4s)、FGC=0(FGCT=0s)
- O%: 平均44.7%、最大61.3%
- M/CCS: 平均28/10%、スパイクなし

### まとめ
- Young周期は安定、Oldも張り付きなし → 正常範囲。
- レイテンシSLO達成。要継続監視(リリース後の差分確認)。

### 次に見るもの(任意)
- 直近リリース前後の差分、p99レイテンシ、CPU/メモリ相関、アロケーションレート

7. ダッシュボード指標(観測向け)

  • YGC/分, FGC回数, GCT/稼働%(GCオーバーヘッド)
  • O%の p95/p99, E%が90%超の割合(周期の安定度)
  • M/CCS の推移
  • 併せてレイテンシ(p95/p99)/スループット/CPU/メモリ同じ時間軸で並置

8. 補助コマンド

  • jstat -gccause -t <pid> <interval> <count>
    直近/現在の GC 原因を把握(FGC や異常な Young が混じる区間で併用)
  • jcmd <pid> GC.class_histogram
    上位クラス占有で巨大配列/キャッシュを推定(Impact: High、本番での頻度に注意)
  • jcmd <pid> VM.flags -all
    実際の GC/ヒープ関連フラグの把握

9. まとめ

  • 本記事ではGC観測データの分析視点にフォーカスしました。
  • チューニングを行う前に、現象の正確な把握と解釈をすることが重要です。
  • 履歴比較(正常時との比較)を第一にし、単発値ではなくトレンドと相関を重視してください。
  • ChatGPTなどの生成AIが使える環境であれば、一時解析をAIに任せて概要を把握し、その後に自分でログを精査するという進め方も効率的でおすすめです。
  • 3部構成でGCについて説明してきましたが、本記事がGC解析の助けとなれば幸いです。

10. 参考リンク

コメント

タイトルとURLをコピーしました