Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Goから学ぶGC -Green Tea GCによる次世代最適化-

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Yporon Yporon
February 20, 2026
380

Goから学ぶGC -Green Tea GCによる次世代最適化-

GCの基本概念と、GoにおけるGCの実装、そしてGreen Tea GCによる次世代最適化について解説しています

Avatar for Yporon

Yporon

February 20, 2026
Tweet

Transcript

  1. G r e e n T e a G C

    に よ る 次 世 代 最 適 化 G O か ら 学 ぶ G C by Renée French CC BY 3.0
  2. GCについての前提知識 スタック・ヒープ プログラムのメモリ空間 ス タ ッ ク : 関 数

    の 実 行 に 必 要 な 一 時 的 な デ ー タ を 格 納。自動管理で高速 ヒープ:動的に確保される大きなデータを格納。GCが 必要で低速
  3. GCについての前提知識 ルートセット オ ブ ジ ェ ク ト が 到

    達 可 能 か ( 生 存 して い る か ) を 判 定 するための始点 全ゴルーチンのスタック グローバル変数(パッケージレベル変数)など ル ー ト セ ッ ト か ら 辿 れ る オ ブ ジ ェ ク ト は 「 生 き て い る」 、辿れないものは「ゴミ」として回収されます。
  4. GCについての前提知識 Write Barrier(書き込みバリア) 並 行 GC 中 に、 ア プ

    リ が オ ブ ジ ェ ク ト を 変 更 し た 際 に GCに通知する仕組み 詳しくは、Tri-color Markingの解説に合わせて説明 します
  5. メモリ構造とGC ルートセット プログラムのメモリ空間 スタック (Stack) processData() data *Data → ヒープ上Data

    temp string = "processing" ← 現在の 実行位置 main() config *Config → ヒープ上Config count int = 42 users []User → ヒープ上配列 ヒープ (Heap) Config host: "localhost" port: 8080 db: *Database []User 配列 [0]: Alice [1]: Bob [2]: Carol Data id: 12345 next: *Data Database connection: "..." pool: [...] OldData 未参照(ガベージ) TempBuffer 未参照(ガベージ) ルートセット(GC Roots )— ガベージコレクションの起点 1. スタック上の 参照 ・実行中の関数のローカル変数 ・関数の引数・一時変数 例: config, users, data → 到達可能 = 生存 2. グローバル / 静的変数 ・プログラム全体で共有 ・シングルトンインスタンス 例: globalCache, logger → 到達可能 = 生存 3. レジスタ / Goroutine スタック ・CPUレジスタ内の参照 ・実行中のGoroutine状態 Goの場合: 各Goroutineのスタック 到達不可能 = ガベージ → 回収 生存オブジェクト ガベージ(回収対象) 参照
  6. Mark & Sweep ガベージコレクション ① 初期状態 ルートセット A B C

    D E 全オブジェクトが未マーク状態 Root → A, B / A → E / B → C D はどこからも参照されていない ▶ ② Mark フェーズ ルートセット A B C D E 処理内容: 1. ルートセットからスタート 2. 参照を辿って到達可能なオブジェクトを探索 3. 発見したオブジェクトにマークを付ける ▶ ③ Sweep フェーズ ルートセット A B C FREE E 処理内容: 1. ヒープ全体をスキャン 2. マークがないオブジェクトを特定 3. メモリを解放してフリーリストに追加 ✅ メリット 実装がシンプルで理解しやすい 循環参照を正しく検出・解放できる メモリ使用量の予測が比較的容易 全てのガベージを確実に回収 ⚠ デメリット Stop-the-World(全スレッド停止)が必要 メモリの断片化(フラグメンテーション)が発生 ヒープが大きいと処理時間が長くなる キャッシュ効率が低下する可能性 未マーク マーク済み(生存) 解放済み(FREE)
  7. Tri-color Marking - Go 言語のGC 並行マーキングを実現する三色アルゴリズム 白 (White) 未探索・回収候補 灰

    (Gray) 探索中・参照先未確認 黒 (Black) 探索完了・生存確定 回収 白のまま→解放 Step 1: 初期状態 Root A B C D E 全オブジェクトが白(未探索状態) Step 2: ルートから開始 Root A B C D E ルートから到達可能な A, B を灰色に Step 3: 灰色を処理 Root A B C D E A→E, B→Cの参照先を灰色に / A, B自身を黒に変更 Step 4: 完了 Root A B C FREE E 灰色なし → マーキング完了 白が残っていれば回収対象 🔄 並行実行の 仕組み • Mutator(アプリ)とGCが並行動作 • Write Barrierで参照変更を追跡 • STWは最小限に抑制 • Go 1.5以降で採用 ⚡ Go 言語の 最適化 • Goroutine統合GCスケジューリング • ペーシング: メモリ基準でGC起動 • アシスト: MutatorがGC支援 • 目標: GC停止時間を10ms以下に ✅ 特徴とトレードオフ 利点: レイテンシ低、リアルタイム向き コスト: Write Barrierオーバーヘッド リソース: CPUコア1つをGC専用に メモリ: フットプリントやや大 📝 Write Barrier (書き込みバリア)の役割 並行GC中にアプリがポインタを書き換えた場合、GCが見落とさないように通知する仕組み 例: 黒オブジェクトAが新たに白オブジェクトFを参照 → Write BarrierがFを灰色に変更し、GCの探索対象に追加 これにより、並行実行中でもオブジェクトの見落とし(Lost Update 問題)を防止する ※ 参照関係: Root → A, B / A → E / B → C / D はどこからも参照されていない(到達不能)
  8. Concurrent Mark & Sweep Concurrent Mark & Sweep with Tri-color

    Marking この表現の方がわかりやすいかも、並列でMarkを行う Initial Mark ルートセットを灰色にマーク 短いSTW Write Barrierを有効化 Concurrent Mark gcBgMarkWorkerが並列でヒープ領域をマーキング アプリケーションと同時実行
  9. Concurrent Mark & Sweep Mark Termination マーキング完了処理 Write Barrier無効化 ここも短いSTW

    Concurrent Sweep(並行実行) 未マークオブジェクトを解放 バックグラウンドで実行
  10. 現状のGCの課題感 オブジェクトの参照を辿って探索するため、メモリ空 間を飛び回るアクセスパターンになりうる CPUのL1キャッシュが効かず、DRAMへのアクセス待 ちが頻発 GC 時 間 の 約

    85% が ス キ ャ ン ル ープ、 CPU サ イクル の 35%以上がメモリストール(Design Document) NUMAなどメモリトポロジを考慮していないため、遠 いメモリへのアクセスで遅延が発生
  11. Green Tea GC 🍵 - ページベーススキャニング ❌ 従来のGC (オブジェクトベース) Page

    A ① ④ Page B ⑤ Page C ② ⑥ Page D ③ Page E Page F ⑦ Page G ⑧ Page H ❌ 問題点: • オブジェクトを ランダムにアクセス • メモリ全体を飛び回る(①→②→③... 異なるPage間) • キャッシュミスが頻発(35%のCPU サイクルを浪費) • 同じPageに何度も戻るが既にキャッシュから追い出されている • GCのCPU 時間の 大部分がキャッシュ待ちで浪費 🍵 Green Tea GC (ページベース) Page A ✓ 1 2 1 Page B ⏳ 3 4 5 2 Page C 6 7 3 Page D 8 4 Page E Page F 9 Page G 10 Page H ✅ 改善点: • Page単位で連続してスキャン( 局所性を最大化) • メモリ局所性が高い(8KiB 境界でアライメント) • GCオーバーヘッド10 40% 削減(GC多用プログラム) • バッチ効果: Page内の複数オブジェクトをまとめて処理 • 新しいamd64 CPU (Ice Lake/Zen 4 でさらに約10% 改善 白(未探索) 灰(探索中) 黒(完了) スキャン済みPage 処理中Page ランダムアクセス N スキャン順序
  12. GreenTeaGCのアプローチ 🍵 従来のアルゴリズムの延長にある その上で、オブジェクト単位ではなくpageを処理単位とする 従来はオブジェクトを発見後すぐスキャンしていた Green Tea GC で は

    参 照 先 の オ ブ ジ ェ ク ト を 見 つ け ても pageにマークビットを立てるだけ そのpageを処理する順番が来たら、page内のマーク済み オブジェクトをまとめて連続的にスキャンする
  13. 何が良くなるのか キャッシュ効率の向上 pageがL1キャッシュに丸ごと収まる page 内 の オ ブ ジ ェ

    ク ト を 連 続 ス キ ャ ン す る た め 、 一 度CPUキャッシュに載せたデータを再利用できる 従来のようなDRAMを飛び回るアクセスが不要になる スキャン回数の削減 即時スキャンに比べて、同じpageへの再訪問がなくな りスキャンのオーバーヘッド自体が減る
  14. 何が良くなるのか マルチコア環境でのスケーラビリティ ワーカーごとにスパ ン単位のローカルキューを持つ 暇 な ワ ー カ ー

    が 他 の ワ ー カ ー か ら ス パ ン を 奪 う (work stealing) グローバルキューへのロック競合が減り、コア数に応 じてスケールする ベクトル命令(AVX-512)による追加高速化 スパ ン内のオブジェクトは同一サイズで規則的に並ぶ た め 、 SIMD 命 令 で ビ ッ ト マ ッ プ 操 作 を ま と め て 処 理 できる
  15. まとめ GCの基礎 不要メモリの自動回収で安全・効率的な開発を実現 GoのGC実装 Concurrent Mark & Sweep Green Tea

    GC メモリアクセスの最適化を目指し、オブジェクト単位 ではなくpage単位でスキャンする