Slide 1

Slide 1 text

G r e e n T e a G C に よ る 次 世 代 最 適 化 G O か ら 学 ぶ G C by Renée French CC BY 3.0

Slide 2

Slide 2 text

伊東祐哉(𝕏: @go_poron10) ダイレクト出版株式会社/Tech Lead ECサイトのバックエンド リアーキテクチャ・システム設計 社内用MCP 趣味 麻雀 🀄, 読書 スライド資料は𝕏にアップロードします 自己紹介

Slide 3

Slide 3 text

ロワイヤルテラッセの「生パイ」 絶品かつ東京では買えない 小さい頃から仙台に来たら必ず食べてます 綺麗に食べられないことしか欠点がないです 余談

Slide 4

Slide 4 text

突然ですが、Go1.26のリリースノートは 読みましたでしょうか?

Slide 5

Slide 5 text

Green Tea GC Go 1.26 Release Notes#runtime

Slide 6

Slide 6 text

Green Tea GCのデフォルト化 🎉🎉

Slide 7

Slide 7 text

Green Tea GCって何がすごい? てかそもそもGCって...?

Slide 8

Slide 8 text

今日のゴール GCのイメージが掴めること Green Tea GC の 何 が 偉 い の か と 、 思 想 を 理解できること

Slide 9

Slide 9 text

目次 GCとは 現在のGoのGC実装 Green Tea GCのアプローチ まとめ

Slide 10

Slide 10 text

GCってなんなん

Slide 11

Slide 11 text

GCとは GC = Garbage Collection 不要になったメモリを自動で回収する仕組み

Slide 12

Slide 12 text

メモリを回収しないとどうなるの? 使い終わったメモリが解放されず、どんどん蓄積 →メモリリーク Out of Memory (OOM) エラーでプログラム強制終了 メモリ不足でスワップ(ディスクI/O)が発生 アプリケーションのパフォーマンス低下

Slide 13

Slide 13 text

GCの目的 安全性 メモリリークやダングリングポインタの回避 セキュリティリスクの低減 開発効率の向上 malloc/freeの対応管理から解放 コードがシンプルになり、メモリ管理のバグを減らせる 安定性 ランタイムによる最適化で性能が安定 サービス品質の向上

Slide 14

Slide 14 text

GoにおけるGC Concurrent Tri-color Mark & Sweep

Slide 15

Slide 15 text

GCの前提知識紹介

Slide 16

Slide 16 text

GCについての前提知識 スタック・ヒープ プログラムのメモリ空間 ス タ ッ ク : 関 数 の 実 行 に 必 要 な 一 時 的 な デ ー タ を 格 納。自動管理で高速 ヒープ:動的に確保される大きなデータを格納。GCが 必要で低速

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

GCについての前提知識 STW(Stop The World) GC実行中にアプリケーションを一時停止すること GC中にオブジェクトが変更されると、正確な判定がで きない すべてを停止させて「スナップショット」を取る必要 がある

Slide 19

Slide 19 text

GCについての前提知識 Write Barrier(書き込みバリア) 並 行 GC 中 に、 ア プ リ が オ ブ ジ ェ ク ト を 変 更 し た 際 に GCに通知する仕組み 詳しくは、Tri-color Markingの解説に合わせて説明 します

Slide 20

Slide 20 text

メモリ構造と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のスタック 到達不可能 = ガベージ → 回収 生存オブジェクト ガベージ(回収対象) 参照

Slide 21

Slide 21 text

Mark & Sweep

Slide 22

Slide 22 text

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)

Slide 23

Slide 23 text

concurrent Tri-color Marking

Slide 24

Slide 24 text

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 はどこからも参照されていない(到達不能)

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Concurrent Mark & Sweep Mark Termination マーキング完了処理 Write Barrier無効化 ここも短いSTW Concurrent Sweep(並行実行) 未マークオブジェクトを解放 バックグラウンドで実行

Slide 27

Slide 27 text

現状のGC GoのGCはよくできている。STWを最小化し、 並行でマーキングできる設計。 でも本当に課題はないのか?

Slide 28

Slide 28 text

現状のGCの課題感 メモリアクセスが非効率な場合がある

Slide 29

Slide 29 text

現状のGCの課題感 オブジェクトの参照を辿って探索するため、メモリ空 間を飛び回るアクセスパターンになりうる CPUのL1キャッシュが効かず、DRAMへのアクセス待 ちが頻発 GC 時 間 の 約 85% が ス キ ャ ン ル ープ、 CPU サ イクル の 35%以上がメモリストール(Design Document) NUMAなどメモリトポロジを考慮していないため、遠 いメモリへのアクセスで遅延が発生

Slide 30

Slide 30 text

現状のGCの思想 「プロセッサ中心」の思想 メモリアクセスの効率性を犠牲にしてでも、全てのCPU コアを最大限活用することを最優先 現在のハードウェアの進化によりミスマッチが生じるよ うになった

Slide 31

Slide 31 text

ハードウェアトレンドとのミスマッチ CPUの進化 コア数は増加し続けている(8, 16, 64コア...) 処理能力は向上 メモリの進化 速度向上は緩やか CPU-メモリ速度差は年々拡大(Memory Wall問題)

Slide 32

Slide 32 text

ハードウェアトレンドとのミスマッチ

Slide 33

Slide 33 text

時代のハードウェアに最適化されていない?

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

GreenTeaGCのアプローチ 🍵 "Work with pages, not objects." オブジェクト単位ではなくpage単位でスキャンする

Slide 36

Slide 36 text

どんな動きになるか公式ブログを使って 説明します

Slide 37

Slide 37 text

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 スキャン順序

Slide 38

Slide 38 text

従来のオブジェクトベーススキャン メモリを縦横無尽に飛び回り、スキャンを繰り返す 特に、ページ間やページ内の異なる部分間を頻繁に移動する CPUキャッシュには、最近アクセスされたメモリと、それに近いメモ リが格納される。しかし、互いを指す2つのオブジェクトが、メモリ 内でも互いに近い位置にあるという保証はない オブジェクトベースでのスキャンではこの点が考慮されていない

Slide 39

Slide 39 text

GreenTeaGCのアプローチ 🍵

Slide 40

Slide 40 text

GreenTeaGCのアプローチ 🍵 従来のアルゴリズムの延長にある その上で、オブジェクト単位ではなくpageを処理単位とする 従来はオブジェクトを発見後すぐスキャンしていた Green Tea GC で は 参 照 先 の オ ブ ジ ェ ク ト を 見 つ け ても pageにマークビットを立てるだけ そのpageを処理する順番が来たら、page内のマーク済み オブジェクトをまとめて連続的にスキャンする

Slide 41

Slide 41 text

何が良くなるのか?

Slide 42

Slide 42 text

何が良くなるのか キャッシュ効率の向上 pageがL1キャッシュに丸ごと収まる page 内 の オ ブ ジ ェ ク ト を 連 続 ス キ ャ ン す る た め 、 一 度CPUキャッシュに載せたデータを再利用できる 従来のようなDRAMを飛び回るアクセスが不要になる スキャン回数の削減 即時スキャンに比べて、同じpageへの再訪問がなくな りスキャンのオーバーヘッド自体が減る

Slide 43

Slide 43 text

何が良くなるのか マルチコア環境でのスケーラビリティ ワーカーごとにスパ ン単位のローカルキューを持つ 暇 な ワ ー カ ー が 他 の ワ ー カ ー か ら ス パ ン を 奪 う (work stealing) グローバルキューへのロック競合が減り、コア数に応 じてスケールする ベクトル命令(AVX-512)による追加高速化 スパ ン内のオブジェクトは同一サイズで規則的に並ぶ た め 、 SIMD 命 令 で ビ ッ ト マ ッ プ 操 作 を ま と め て 処 理 できる

Slide 44

Slide 44 text

何が良くなるのか キャッシュ効率:page単位の連続スキャンでCPUキャッシュを最大活用 スキャン回数 :pageへの再訪問を排除しオーバーヘッド削減 並列処理 :ローカルキュー + work stealingでマルチコアにスケール ベクトル命令による追加高速化 :同一サイズの規則配置を活かす

Slide 45

Slide 45 text

GreenTea GC Go1.26でデフォルト化 https://go.dev/doc/go1.26#new-garbage-collector GCを多用する実アプリケーションにおいて、オーバーヘッド が10~40%程度削減見込み 新しいamd64ベースのCPUプラットフォーム(Intel Ice Lake or AMD Zen 4 and newer) で は 、 GC の オ ーバ ー ヘ ッ ド が さ らに10%改善見込み GOEXPERIMENT=nogreenteagcで無効化 この設定もGo1.27で削除予定

Slide 46

Slide 46 text

まとめ

Slide 47

Slide 47 text

まとめ GCの基礎 不要メモリの自動回収で安全・効率的な開発を実現 GoのGC実装 Concurrent Mark & Sweep Green Tea GC メモリアクセスの最適化を目指し、オブジェクト単位 ではなくpage単位でスキャンする

Slide 48

Slide 48 text

余談

Slide 49

Slide 49 text

参考文献 https://github.com/golang/go/issues/73581 https://antonz.org/go-1-26/ https://go.dev/blog/greenteagc https://go.dev/doc/go1.25 https://qiita.com/gold- kou/items/4431d3dd41606d41732b https://www.dolthub.com/blog/2025-09-26-greentea- gc-with-dolt/

Slide 50

Slide 50 text

参考文献2 https://siddharthav.medium.com/green-tea-garbage- collector-63233aa5a9b5 https://speakerdeck.com/zchee/the-current-status- of-green-tea-gc

Slide 51

Slide 51 text

ご静聴いただきありがとうございました T H A N K Y O U