HotSpotのGCメモ as of December 2012

注:Sunの資料などを読んだ自分メモです。

default GCはyoungとtenuedのgenerationを持つ。

young := eden+from+to
GC時(eden,from)は必ず空になる

EDEN FROM TO TENUED
a b c d
{GC : a不要}
b c d

MIN <= eden+from+to <= MAX
where
MIN = min(MaxNewSize, max(NewSize,heap/(NewRatio+1)))
MAX = MaxNewSize

Perm領域 ∋ Class, Method etc.

CMS ( Concurrent Mark-Sweep) aka. concurrent low pause collection

(gencon)
- TENUREDに対するGC
- 多くの処理をアプリとは並行(concurrently)に行い停止を減らす。
- 一定割合(default 68%) のTENUEDが使われると発動。

CMSの6フェーズ

1. 全スレッドを止め、根から直接到達可能なobjをマークしスレッドを再開

2. 推移的に、紐付くobjもマークしていく。(concurrent marking)

3. フェーズ2の間に変更されているobjがあるか再度スキャンする。

4. 一回stop-the-worldしてマークをやり終える。中には、この時点で不要になっているにもかかわらずマークしてしまっているのもあるが、それらは今回のGCではあきらめ次回に回すことにする。

5. 不要領域を回収する。生きてるobjは移動しない。

6. 後始末


CMSについて
  • 大メモリで、たまにであってもOldGCで時間がかかるのがイヤなとき。
  • CMSはコンパクションを行わない。

→非連続になるので、空きリストを管理するコストが発生する。

  • デフラグ的なことはやる。
  • OLDが68%を超えたか、今までのGC回数とOLDの消費速度から算出したタイミングのいずれかをトリガーとして発動する。
CMSまとめ(パラレルに比べ)
  • OldGCの時間↓
  • NewGCの時間やや↑
  • スループットやや↓
  • ヒープサイズ↑
incremental mode
  • 並行フェーズを一度に行わず少しずつ行うことで、CPU数が少ない場合に停止時間を短縮する。
CMS用途
  • 長寿命の大オブジェクト
  • 停止時間少
  • -XX:+UseConcMarkSweepGC

TLAB : thread-local Allocation Buffers

  • Parallelでもたまに長いFull GCが起こる。
  • ParallelはJDK5の -server のデフォルト

Parallel Compacting Collector

  • OLD領域には左からobjを割り当てて行くので、左側の濃度が濃い。
  • 濃いところをGCしてもコストに引き合う効果がない。
  • そこでコストが引き合うところを見定めそこから右のみについてGCを実施
  • 停止が短くすむ。
  • 多くのプロセスがCPUを共用しJVMだけがCPUを独占すべきでないような場合には不向き。
  • XX:+UserParallelOldGC
  • スレッド減らすときは -XX:ParallelGCThreads=n
      • -
振る舞いベースのParallelコレクタtuning

目標値に基づいてヒープサイズとその他のパラメタが自動的に選択される。

  • -XX:MaxGCPauseMillis=n
  • -XX:GCTimeRatio=n
  • JDK6までは String#intern はPerm領域だったが7からは一般ヒープに移された。

G1GC

羊羹的に領域を分ける

各羊羹ごとにlivelinessを算出。
要らなさげなregionのみcollectionを実施

複数の領域からどこか1つにコピーすることにより、compactionを行いつつ停止時間を減らす。

cf. CMS:compactionしない, ParallelOld:全ヒープ走査するから停止時間がかかる

前回のGCに基づいて、どのくらいGCすれば時間目標を満たすか見積もるので、
かなり正確ではあるが絶対ではない。

G1GC: 大容量(>=6GB), 停止時間短(<0.5s)

向いている場合
  • ヒープの50%以上が存命データ
  • オブジェクト割り当て/長寿命化の割合が変動大
  • 望まざる長GC/コンパクション停止がある(>0.5s)


Tiered CompilationによるサーバVM起動の高速化
プロファイリング段階で、インタプリタに加えクライアントコンパイラを使う。

NUMA 複数CPUでプロセッサごとに、ハードウェア上の理由で、速いメモリ(ローカル)とそうでないメモリ(リモート)があるアーキテクチャが存在する。
この場合、メモリを割り当てたスレッドにとって速いメモリのほうをなるべく割り付けたほうがperformanceがよい。パラレルGCの場合に -XX:+UseNUMAで指定する。

  • -Xincgc
  • -Xss スレッドスタックサイズ
  • -XX:-DisableAttachMechanism