#jjug_ccc #ccc_r16 JJUG CCC 2014 Fall 参加レポート / R1-6 Concurrent Mark-Sweep Garbage Collection 再入門

※この投稿は、丸太式 Advent Calendar 2014の9日目です

今日はJJUG CCC 2014 Fallの参加レポート3本目です。

概要

R1-6 Concurrent Mark-Sweep Garbage Collection 再入門
by 久保田 祐史さん (@sugarlife)

メモ

CMS GC

  • GC: 不要なメモリ領域を探し、解放して再利用可能とする
  • Parallel GC: アプリケーションを止めて動く。GC時間は短いが、応答しなくなる
  • Concurrent GC: アプリケーションと同時に動く
  • Concurrent Mark-Sweep GC: ゴミじゃない領域をMarkし、Markされていない領域をSweepして再利用可能にする
    Compactionしないので、メモリ空間が断片化する

HotSpot VMのCMS GC

  • Heap -> New Gen.(Eden, Survivor0, Survivor1), Old Gen.(Tenured)
  • Minor GC: New Gen.に対してParallel Copy GC: アプリケーションを止めて、メモリが断片化しないようにGC
  • Major GC: Old Gen.に対してCMS GC

  • Minor GC: Eden -> Survivor 0, Survivor 0 -> Survivor 1

  • Promotion : Survivor -> Tenured
  • Major GC: Old領域の占有率やHeap使用量増加速度によって発生する
  • CMS GCは安定していない。失敗してSTW:Stop The Worldを伴うFull GCが発生することがある

  • Full GC (with STW): 全領域がGC対象
    Promotion failed, Concurrent mark failed

GCログの読み方

  • タイムスタンプ: Java processのuptime (sec.)
    -XX:+PrintGCDateStampsで、読める時間表記で出力
  • Minor GC: ParNew GC前のNew領域サイズ->GC後のNew領域サイズ(総容量)
    かかった時間は後ろの方に出るtimes (real)を参照
  • Minor GC (promotion): PromoteされたサイズはNew領域の差分 – 全体の領域の差分

  • CMS GC: initial mark
    STWをかけて、ルートオブジェクトから直接たどれるオブジェクトをマーキング

  • concurrent mark
    アプリケーションを再開しつつ、initial markでマーキングされたオブジェクトからたどれる全オブジェクトをマーキング。
    処理中に生成・変更されたオブジェクトはDirty Cardにされる
  • cuncurrent preclean
    STWが発生するRemarkを短縮するため、concurrent mark中にDirty Cardのオブジェクトをマーキング
  • concurrent abortable preclean
    Minor GCによってEden使用量が2MBになるまで最大5秒待つ
  • Remark (Final mark)
    STWしてNew領域を全スキャンして、New領域からOld領域を参照しているものにmark
  • concurrent sweep
    未マークのオブジェクトを改修
  • concurrent reset
    次のCMS GCで使う関連マップをクリアして、initial markの処理にゴミを残さない

注意すべきパターン

  • Full GC: promotion failed: Minor GCでOld領域にPromoteできなかった場合に発生
    断片化を解消するためのFull GC

    • 短命オブジェクトはNew領域で改修するべき(断片化を防ぐ)
    • New領域のサイズを調整する
    • PromoteさせずにNew領域で粘る
    • 兆候: Minor GC後のOld領域より、次のMinor GCの前のOld領域が大きい->短命オブジェクトがOld領域に飛んでる
    • 兆候: Old > NewだがPromotion Failed: Newに大きいオブジェクトしか入っていない
  • Full GC: concurrent mode failure: CMS GC中にもう一度CMS GCが発生しようとした場合

    • CMS GCの改修が間に合っていないので、開始タイミングを早める
    • サーバのスペックをあげる
      • 単純にいメモリを増やすより、CPUスペックをあげるべき
  • GC locker: GCを止める機構。HotSpot初期化や、JNI API呼び出しの一部

  • GC locker: Trying a full collection because scavenge failed
    • GCが止まっているのでNew領域にはいらずOLD領域に割り当て
    • 深刻な断片化、Promote失敗
  • 対策
    • GC Lockerの頻度を下げる
    • 断片化しないGCを使う
    • 短命JVM