Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GC25 Recap+: Advancing Go Garbage Collection wi...
Search
Takuto Nagami
September 30, 2025
Technology
1.1k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GC25 Recap+: Advancing Go Garbage Collection with Green Tea
2025/9/30 Go 1.25 リリースパーティ & GopherCon 2025 報告会にて登壇した際の資料です。
Takuto Nagami
September 30, 2025
More Decks by Takuto Nagami
See All by Takuto Nagami
The Journey of Connecting Japan to the Global Go Community
logica0419
1
50
Discovering Cilium: What eBPF Enabled in K8s Networking
logica0419
0
94
Do Gophers Dream of Stack Overflow?
logica0419
0
50
今こそ学びたいKubernetesネットワーク ~CNIが繋ぐNWとプラットフォームの「フラッと」な対話
logica0419
9
1.3k
キャリア科目では教えてくれない、就活を生き抜く法則
logica0419
2
310
歴史から学ぶ、Goのメモリ管理基礎
logica0419
17
4.2k
【2025改訂版】ITエンジニアとして知っておいてほしい、電子メールという大きな穴
logica0419
2
320
Fundamentals of Memory Management in Go: Learning Through the History
logica0419
1
180
GopherCon Tourのつくりかた
logica0419
2
160
Other Decks in Technology
See All in Technology
20260807_第6回_関東kaggler会LT_claw系bot xangiと始める、"寂しくない" kaggle
sugupoko
0
190
FORENSIA: ローカルLLMフォレンジックハーネス
sumeshi
2
280
SmartHR Engineering Team Deck
smarthr
0
820
Redmine 7.0 新機能・機能強化解説(OSC2026京都ダイジェスト版)
vividtone
1
200
AI駆動開発は個人技からチーム戦へ:組織でAIを使いこなすための実践設計
moongift
PRO
0
480
ガバメントクラウドでのランサムウェア対策
techniczna
2
980
Cursor Meetup Sapporo - Cursor物語 続編
cocacola917
0
140
攻撃と防御で学ぶAI時代のプロダクトセキュリティ演習
recruitengineers
PRO
6
2.1k
今こそ聞きたいソフトウェア設計 ドメイン駆動設計再入門
masuda220
PRO
17
6.7k
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.3k
組織にどうSREを根付かせるか?〜IVRyの場合〜
abnoumaru
0
330
制約理論(ToC)入門 2026版
recruitengineers
PRO
6
2k
Featured
See All Featured
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Building Adaptive Systems
keathley
44
3.2k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.7k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
460
A designer walks into a library…
pauljervisheath
211
24k
Paper Plane
katiecoart
PRO
2
52k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
590
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
Transcript
Takuto Nagami @logica0419 Recap+: Advancing Go Garbage Collection with Green
Tea
今回Recapするのは… Advancing Go Garbage Collection with Green Tea by Michael
Knyszek
要約 (TL;DR): Go 1.26から ガベージコレクションが 速くなります。
本題に入る前に 前提知識をおさらい しておきましょう
スタック・ヒープと ガベージコレクション
アプリケーションから見たメモリ . . . • Key-value storeの形で表される ◦ Key: Memory
address ◦ Value: 各アドレス1バイト • ほとんどの高級言語は、変数を メモリに格納する時、スタック とヒープの2つの領域を(言語側 で作って)使い分ける 0x0000 0x0001 0x0002 0x0003
. . . スタック
. . . main() stack frame スタック
. . . main() stack frame 5 スタック {v addr}
. . . main() stack frame 5 a() stack frame
スタック {v addr}
. . . main() stack frame 5 a() stack frame
5 スタック {arg addr} {v addr}
. . . main() stack frame 5 a() stack frame
5 7 スタック {arg addr} {a addr} {v addr}
. . スタック main() stack frame 5 a() stack frame
{arg addr} {a addr} {v addr} 5 7 b() stack frame
. . スタック main() stack frame 5 a() stack frame
{arg addr} {arg addr} {a addr} {v addr} 5 7 b() stack frame 7
. . スタック main() stack frame 5 a() stack frame
{arg addr} {b addr} {arg addr} {a addr} {v addr} 5 7 b() stack frame 7 1
. . . スタック main() stack frame 5 a() stack
frame {arg addr} {a addr} {v addr} 5 7
. . . スタック main() stack frame 5 {v addr}
. . . スタック プログラム終了
スタックが苦手なデータ • 大きなデータ ◦ Stack Overflowを誘発する • コンパイル時にサイズが決まらないデータ ◦ slice・mapなど
◦ スタックはコンパイル時に全て定義される ▪ 動的にサイズを変えるのは効率が悪い • 複数の関数でまたがって使うデータ ◦ グローバル変数など
ヒープ . . . . . . . main() stack
frame
ヒープ . . . . . . . [] {slice_h
addr} main() stack frame
. . . . . . . [] {slice_h addr}
{slice addr} main() stack frame ヒープ {slice_h addr}
ヒープ内でのオブジェクト管理 • 色んなデータ(オブジェクト)がヒープに入る ◦ バラバラに入れていたら管理が面倒 int (8 byte) struct (可変サイズ)
ポインタ (8 byte)
… … ヒープ内でのオブジェクト管理 • 同サイズのオブジェクトをスパンでまとめる int (8 byte) struct (8
byte) struct struct (32 byte) struct struct int int スパン1 (8 byte用) スパン2 (8 byte用) スパン3 (32 byte用) int int
ヒープ内でのオブジェクト管理 • スパン(mspan)はもっと大きな単位でまとめられる ◦ mcentral ▪ 同じサイズのスパンをグループ化 ◦ arena ▪
mheapが1回で引き出してくるメモリ量 ▪ mcentralを複数格納 ◦ mheap ▪ ヒープ本体
ガベージコレクション(GC) • Cなどでは、ヒープに置いたデータを使わなくなった時 プログラマーが明示的に削除 ◦ 削除忘れによってメモリ使用量が無限に増える memory leakが多発 ↓ •
要らなくなったヒープ内のデータを自動的に削除する 機能がガベージコレクション
これまでのGCと その挙動
GoのGC • Mark and Sweepアルゴリズム ◦ Mark phase: まだ使われているオブジェクトを確認 ◦
Sweep phase: マークされていない物を削除 • Tri-color markingを使うことで中断可能に ◦ 詳しいことは今回割愛 • 色々頑張ってアプリケーションと並列で実行 ◦ 今回割愛
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T ここから、Tri-color markingの root scan phase
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T ここから、Tri-color markingの mark phase
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T ここから sweep phase
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T [4]*T [4]*T
メモリ局所性と OSのメモリ読み込み戦略
メモリ局所性(参照の局所性)とは • データアクセスの傾向に関する概念 • 時間的局所性 ◦ 同じデータには近いうちに再度アクセスされやすい • 空間的局所性 ◦
近い場所にあるデータは一緒にアクセスされやすい • ↑ のような傾向が強いと「局所性が高い」 • 世の中のタスクのほとんどは局所性が高いので、OSは それに合わせて最適化している
OSのメモリ読み込み戦略 • 多段キャッシュをする ◦ CPUの処理部に近づくほど、小さく速い • この構造を活かすための読み込み戦略が… CPU内 キャッシュ (多段)
メモリ (DRAM) ストレージ 小さくて速い 大きくて遅い
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい ページ1 (4 kB)
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 データを 使って処理 ページ1 (4 kB)
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 次(ページ1)の データ欲しい ページ1 (4 kB)
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 次(ページ1)の データ欲しい ページ1 (4 kB)
OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)
ページ3 (4 kB) CPU キャッシュ CPU 処理部 次データを 使って処理 ページ1 (4 kB)
キャッシュ戦略は 時間・空間的局所性が高い タスクに効率化されている キャッシュは局所性の高さに対処するという表現が自然
OSのメモリ読み込み戦略 • 近くのページをまとめて取ることも (更なる空間的 局所性対策) メモリ ページ1 (4 kB) ページ2
(4 kB) ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい
OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4
kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4
kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4
kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4
kB) CPU キャッシュ CPU 処理部 データを 使って処理 ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4
kB) CPU キャッシュ CPU 処理部 ページ2内 データ欲しい ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4
kB) CPU キャッシュ CPU 処理部 ページ2内 データ欲しい ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4
kB) CPU キャッシュ CPU 処理部 データを 使って処理 ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
OSは様々な手法を用いて メモリ局所性の高いタスクを 効率的に走らせている これがGreen Teaへの伏線
Green Tea🍵とその挙動
… … おさらい: Goのヒープ管理 • 同サイズのオブジェクトをスパンでまとめる int (8 byte) struct
(8 byte) struct struct (32 byte) struct struct int int スパン1 (8 byte用) スパン2 (8 byte用) スパン3 (32 byte用) int int
スパンの実態 • Goのスパンは、OSのページを数個まとめたもの ◦ 原則となり合ったページが使われる • 同じスパンを読む方がOSのキャッシュ戦略を活かせる object スパン (32kB)
ページ (4 kB) ページ (4 kB) ページ (4 kB) object object object
これまでのGCの課題 • GC自体のメモリ局所性が低い ◦ スパン(ページ)間を飛び回っている ◦ OSのキャッシュ戦略を上手く活かせてない ▪ 遠いページに移動するたびキャッシュリセット •
↑ のせいでメモリ読み込みが遅く、CPUの処理性能を フルで活かせない ◦ CPUの進歩の方が速く、昔とは犠牲にしたいものが 逆になってしまった
Green Tea🍵 • メモリ局所性の高い、新たなマークアルゴリズム ◦ Tri-colorを拡張し、スパンごとにオブジェクトを スキャンする • 実は名前の由来が日本 ◦
Green Teaのプロトタイプを作ったのは、今のTech LeadであるAustine Clements ◦ プロトタイピングの大部分は、Austineさんが横浜 のカフェで大量の抹茶をしばきながら行った
Green Teaはスパンごとの オブジェクトスキャンで 局所性を上げている 実際の挙動を見てみましょう
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T おさらい: ここから sweep phase
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
スタック var x *T var y *T 状態一覧 見てない 見る予定
今見てる もう見た スパンA スパンB スパンC スパンD T T T T T [4]*T [4]*T
実験: Green Teaって ホントに速いの?
効きそうなパターンを作成してみた
やってること 100万件の slice s □□□...
やってること s □□□... T a:□ b:□
やってること s □□□... T a:□ b:□ int □
やってること s □□□... T a:□ b:□ int □ まだsは 使う状態で
GC
T T T T []*T スタック var s *[]T スパン
(T 用) スパン (int 用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b
T T T T []*T スタック var s *[]T スパン
(T 用) スパン (int 用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b これまでなら
T T T T []*T スタック var s *[]T スパン
(T 用) スパン (int 用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b
T T T T []*T スタック var s *[]T スパン
(T 用) スパン (int 用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b
T T T T []*T スタック var s *[]T スパン
(T 用) スパン (int 用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b Green Teaなら
T T T T []*T スタック var s *[]T スパン
(T 用) スパン (int 用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b
T T T T []*T スタック var s *[]T スパン
(T 用) スパン (int 用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b
T T T T []*T スパン (T 用) スパン (int
用) スパン ([]*T 用) T T.b T.b T.b T.b T.b T.b T.b スタック var s *[]T こうなって欲しい (実際に確かめてはいません)
こんな感じで実行 (最適化は切った)
結果
結果 5回とも ちゃんと 速い
まとめ • Green Teaはスパン単位のスキャンで局所性をup • とてもシンプル、だけど一部のケースで強力 ◦ OSの特性をよく活かす方向性 Go 1.26から
ガベージコレクションが 速くなります。
ありがとう ございました Green Tea、試してみてね!