主要なGCアルゴリズム
投稿日 March 14, 2024 • 1分で読めます • 210文字 • 言語を選択: Korean、English
Table of contents
『Java最適化』スタディをしながら主要なGCアルゴリズムについてより深く勉強するために書いた記事です。
Serial GC
- 最も単純なGC実装
- STW(Stop-The-World)後、1つのスレッドでのみGCを実行
- mark-sweep-compactアルゴリズムを使用
- マルチスレッド環境には不適切
❖ Serial GC有効化フラグ
java -XX:+UseSerialGC
Parallel GC
- Java 5〜8までのデフォルトGC
- GC処理率を最大化するためThroughput Collectorとも呼ばれる
- メモリ空間が十分でコア数が多い場合に有利なアルゴリズム
- フラグを通じてGCに使用する最大スレッド数、最大停止時間、GC実行時間比率を設定可能
-XX:ParallelGCThreads=<N>-XX:MaxGCPauseMillis=<N>-XX:GCTimeRatio=<N>
❖ Parallel GC有効化フラグ
java -XX:+UseParallelGC
Parallel Old GC
- Parallel GCのOld領域バージョン
- Old領域までマルチスレッドでGCを実行
- Old領域に対してMark-Summary-Compactアルゴリズムを使用
- Markフェーズ:Old領域をリージョン別に分け、リージョン別に頻繁に参照されるオブジェクトをマーキング
- Summaryフェーズ:生き残ったオブジェクトの中で密度が高い部分がどこかdense prefixを決め、これを基準にcompact領域を減らす
- Compactフェーズ:compact領域をdestinationとsourceに分け、生き残ったオブジェクトをdestinationに移動し、参照されていないオブジェクトは削除
❖ Parallel Old GC有効化フラグ
java -XX:+UseParallelOldGC
CMS GC
Concurrent Mark Sweep
❖ Concurrentが付くとアプリケーション動作中に同時に実行されるという意味
- Initial Markフェーズ:クラスローダーから最も近いオブジェクトの中で生きているオブジェクトだけを見つけて終了
- Concurrent Markフェーズ:生きていると確認したオブジェクトをルートとして参照されるオブジェクトをマーキング
- Remarkフェーズ:Concurrent Markフェーズで新しく追加されたり参照が切れたオブジェクトをマーキング
- Concurrent Sweepフェーズ:マーキングされていないオブジェクトを削除
長所
- STW時間が非常に短い
- Low Latency GCとも呼ばれる
- 低い応答速度が重要な場合に使用される
短所
- CPUとメモリ使用量が多い
- compactionフェーズがないためメモリ断片化が発生する可能性がある
- 断片化されたメモリが多いため、compaction作業を行うとSTW時間がさらに長くなる
❖ CMS GC有効化フラグ
java -XX:+UseConcMarkSweepGC
G1 GC
Garbage First
- Java 9からのデフォルトGC
- これまでのGCとは全く異なる方式
- メモリ空間が豊富なマルチプロセッサ環境で使用
- ヒープメモリを同じサイズのRegionという領域に分けてメモリを管理
- 各リージョンは論理的に区分される(Eden、Survivor、Old、Humongous、Available/Unused)
- Humongous:リージョンサイズの50%を超える大きなオブジェクトを格納する領域
- Available/Unused:まだ使用されていない領域
GC実行フェーズ
- グローバルマーキングフェーズ:リージョン別オブジェクト活性度を判断
- スイープフェーズ:ほぼ空のリージョンから優先的にガベージを収集して大きな空き容量を確保
RSet(Remembered Set)
- 領域ごとに1つ存在する、外部からヒープ領域内部を参照するためのリファレンス管理装置
- floating garbageを追跡するための用途
- floating garbage:すでに死んだオブジェクトが参照しているオブジェクトで、生きているように見えるオブジェクト
Minor GC
- Eden領域がいっぱいになると実行
- Eden領域の生き残ったオブジェクトをSurvivor領域に移動
- 空になったEden領域をAvailable/Unused領域に指定
Major GC
- Initial Markフェーズ:Oldリージョンのオブジェクトが参照するSurvivor領域のオブジェクトをマーキング(STW)
- Root Region Scanフェーズ:上記フェーズで見つけたSurvivorオブジェクトに対するスキャン作業
- Concurrent Markフェーズ:ヒープ全体に対するスキャン作業を実施 → ガベージがないリージョンは次のフェーズから除外
- Remarkフェーズ:最終的にGC対象から除外するオブジェクトを識別(STW)
- Cleanupフェーズ:生きているオブジェクトが最も少ないリージョンに対する未使用オブジェクト削除作業(STW)
- Copyフェーズ:Cleanup後も完全に空にならなかった生きているオブジェクトを新しいリージョンに移すことでcompaction作業を実行(STW)
❖ G1 GC有効化フラグ
java -XX:+UseG1GC
Z GC
- Java 11で実験バージョンとして登場、その後Java 15から正式バージョンをリリース
- STW時間を10ms以下に!
- 低レイテンシを必要とする同時性の高い高コスト作業に適している
- 8MB〜16TBサイズのヒープ処理が可能
- G1 GCと同様にヒープを領域別に分けて管理するが、各領域のサイズは異なる
- regionの代わりにZPageという論理単位で区分
- small(2 MB)、medium(32 MB)、large(N * 2 MB)の3タイプを持つ
Colored pointers
- オブジェクトを指す変数のポインタで64bitメモリを活用してオブジェクトの状態値を格納
- そのため64bit OSでのみ使用可能!
- 42bitはオブジェクトのアドレス値として活用
- 4bitはオブジェクトの状態値を表現
- Finalizable:finalizerを通じてのみアクセス可能なオブジェクト(ガベージ)
- Remapped:オブジェクトの再配置の有無を表示
- Marked 1 / 0:アクセス可能なオブジェクトを表示
- 仮想アドレスと実アドレスマッピング演算の節約のため、すべての仮想アドレスに対してmmap(multi-mapping)を実行
- これによりメモリ使用量が3倍に増加
Load barriers
- オブジェクトを参照する時に実行されるコード
- ヒープにあるオブジェクトが参照可能な状態かを検査
- 問題がある場合はslow pathというプロセスを実行した後に参照を進行
- オブジェクトを参照する前にバリアで防いでくれるというイメージで連想すると理解しやすい!
- G1 GCとは異なり、メモリ再配置過程でSTWが発生しないようにする
- Remap MarkとRellocation Setを確認しながら参照とmarkを更新
GC実行フェーズ
- Pause Mark Startフェーズ:ZGCのルートから指すオブジェクトにMark表示(Live Object)
- 各スレッドが自分のローカル変数をスキャンしてGCルートセットを作成(非常に短いSTW)
- Concurrent Mark/Remapフェーズ:オブジェクトの参照を探索しながらすべてのオブジェクトにMark表示
- GCルートからアクセス可能なオブジェクトに対するcoloringとremappingを実行
- Pause Mark Endフェーズ:新しく入ってきたオブジェクトに対するMark表示
- Concurrent Prepare for Relocateフェーズ:再配置する領域を見つけてRelocation Setに配置
- Relocation Set:ガベージが1つでもあるZPageの集合
- Pause Relocate Startフェーズ:すべてのルート参照の再配置を進行し更新
- Concurrent Relocateフェーズ:Load barriersを使用してすべてのオブジェクトを再配置後、参照を修正
- フォワーディングテーブルを使用してオブジェクトのアドレスを更新
❖ Z GCの圧倒的なSTW時間
❖ Z GC有効化フラグ
java -XX:+UseZGC
⚠️ Java 15以前のバージョンでは-XX:+UnlockExperimentalVMOptionsオプションを追加する必要がある
References
- https://d2.naver.com/helloworld/1329
- https://www.baeldung.com/jvm-garbage-collectors
- https://velog.io/@guswlsapdlf/Java-GC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98
- https://huisam.tistory.com/entry/jvmgc
- https://renuevo.github.io/java/garbage-collection/
- https://www.baeldung.com/jvm-zgc-garbage-collector
- https://d2.naver.com/helloworld/0128759