TL;DR
Go の新しいガベージコレクタ。オブジェクトを 1 つずつ走査する代わりに、メモリ上の大きな連続したブロック(span)単位でまとめて走査する。Go 1.25 では試験機能として提供された。
なぜ必要か
従来の GC はヒープをオブジェクトのグラフとしてたどる三色マーク法で、オブジェクトを 1 つずつ走査する。ポインタをたどるたびに離れたメモリ領域へ飛ぶので、メモリの局所性が悪い。Issue では、GC の時間の約 85% が走査のループに使われ、そのサイクルの 35% 以上がメモリ待ちで止まっていたと報告されている。
仕組み
同じサイズのオブジェクトを持つ 8 KiB の span を単位に、どのオブジェクトがマーク済みかを span ごとに記録する。キューにはオブジェクトではなく span を積み、span に溜まったマーク待ちのオブジェクトを 1 回でまとめて走査する。大きなオブジェクトは従来どおりのアルゴリズムで扱う。
Instead of scanning individual objects, the garbage collector scans memory in much larger, contiguous blocks.
マイクロベンチマークでは GC の CPU コストが約 10〜50% 減り、L1、L2 キャッシュのミスもほぼ半分になった。一方、広いベンチマークでは結果がまちまちで、悪化したものもある。
例
Go 1.25 では、ビルド時に環境変数で有効にする。
GOEXPERIMENT=greenteagc go buildIssue によると、その後デフォルトで有効になり、GOEXPERIMENT=nogreenteagc で無効にできる。
自分の理解
現時点の GC について書かれた A Guide to the Go Garbage Collector も、Green Tea に変わったら書き換わると思うので、アーカイブしておきたい。
関連
- ガベージコレクション
- A Guide to the Go Garbage Collector
- Green Tea Garbage Collector の今:Go言語のコアチームによる試行錯誤の過程と共にメモリ管理最適化の実装を読み解く