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

GC25 Recap+: Advancing Go Garbage Collection wi...

Avatar for Takuto Nagami Takuto Nagami
September 30, 2025

GC25 Recap+: Advancing Go Garbage Collection with Green Tea

2025/9/30 Go 1.25 リリースパーティ & GopherCon 2025 報告会にて登壇した際の資料です。

Avatar for Takuto Nagami

Takuto Nagami

September 30, 2025
Tweet

More Decks by Takuto Nagami

Other Decks in Technology

Transcript

  1. アプリケーションから見たメモリ . . . • Key-value storeの形で表される ◦ Key: Memory

    address ◦ Value: 各アドレス1バイト • ほとんどの高級言語は、変数を メモリに格納する時、スタック とヒープの2つの領域を(言語側 で作って)使い分ける 0x0000 0x0001 0x0002 0x0003
  2. . . . main() stack frame 5 a() stack frame

    5 スタック {arg addr} {v addr}
  3. . . . main() stack frame 5 a() stack frame

    5 7 スタック {arg addr} {a addr} {v addr}
  4. . . スタック main() stack frame 5 a() stack frame

    {arg addr} {a addr} {v addr} 5 7 b() stack frame
  5. . . スタック main() stack frame 5 a() stack frame

    {arg addr} {arg addr} {a addr} {v addr} 5 7 b() stack frame 7
  6. . . スタック main() stack frame 5 a() stack frame

    {arg addr} {b addr} {arg addr} {a addr} {v addr} 5 7 b() stack frame 7 1
  7. . . . スタック main() stack frame 5 a() stack

    frame {arg addr} {a addr} {v addr} 5 7
  8. スタックが苦手なデータ • 大きなデータ ◦ Stack Overflowを誘発する • コンパイル時にサイズが決まらないデータ ◦ slice・mapなど

    ◦ スタックはコンパイル時に全て定義される ▪ 動的にサイズを変えるのは効率が悪い • 複数の関数でまたがって使うデータ ◦ グローバル変数など
  9. ヒープ . . . . . . . [] {slice_h

    addr} main() stack frame
  10. . . . . . . . [] {slice_h addr}

    {slice addr} main() stack frame ヒープ {slice_h addr}
  11. … … ヒープ内でのオブジェクト管理 • 同サイズのオブジェクトをスパンでまとめる 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
  12. GoのGC • Mark and Sweepアルゴリズム ◦ Mark phase: まだ使われているオブジェクトを確認 ◦

    Sweep phase: マークされていない物を削除 • Tri-color markingを使うことで中断可能に ◦ 詳しいことは今回割愛 • 色々頑張ってアプリケーションと並列で実行 ◦ 今回割愛
  13. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  14. スタック 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
  15. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  16. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  17. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  18. スタック 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
  19. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  20. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  21. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  22. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  23. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  24. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  25. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  26. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  27. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  28. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  29. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  30. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  31. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  32. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  33. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  34. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  35. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  36. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  37. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  38. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  39. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  40. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  41. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  42. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  43. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  44. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T ここから sweep phase
  45. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  46. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  47. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T [4]*T [4]*T
  48. メモリ局所性(参照の局所性)とは • データアクセスの傾向に関する概念 • 時間的局所性 ◦ 同じデータには近いうちに再度アクセスされやすい • 空間的局所性 ◦

    近い場所にあるデータは一緒にアクセスされやすい • ↑ のような傾向が強いと「局所性が高い」 • 世の中のタスクのほとんどは局所性が高いので、OSは それに合わせて最適化している
  49. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい
  50. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい
  51. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい
  52. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい ページ1 (4 kB)
  53. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 データを 使って処理 ページ1 (4 kB)
  54. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 次(ページ1)の データ欲しい ページ1 (4 kB)
  55. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 次(ページ1)の データ欲しい ページ1 (4 kB)
  56. OSのメモリ読み込み戦略 • ページングを行う メモリ ページ1 (4 kB) ページ2 (4 kB)

    ページ3 (4 kB) CPU キャッシュ CPU 処理部 次データを 使って処理 ページ1 (4 kB)
  57. OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4

    kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
  58. OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4

    kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
  59. OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4

    kB) CPU キャッシュ CPU 処理部 ページ1内 データ欲しい ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
  60. OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4

    kB) CPU キャッシュ CPU 処理部 データを 使って処理 ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
  61. OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4

    kB) CPU キャッシュ CPU 処理部 ページ2内 データ欲しい ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
  62. OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4

    kB) CPU キャッシュ CPU 処理部 ページ2内 データ欲しい ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
  63. OSのメモリ読み込み戦略 メモリ ページ1 (4 kB) ページ2 (4 kB) ページ3 (4

    kB) CPU キャッシュ CPU 処理部 データを 使って処理 ページ1 (4 kB) ページ2 (4 kB) • 近くのページをまとめて取ることも (更なる空間的 局所性対策)
  64. … … おさらい: 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
  65. これまでのGCの課題 • GC自体のメモリ局所性が低い ◦ スパン(ページ)間を飛び回っている ◦ OSのキャッシュ戦略を上手く活かせてない ▪ 遠いページに移動するたびキャッシュリセット •

    ↑ のせいでメモリ読み込みが遅く、CPUの処理性能を フルで活かせない ◦ CPUの進歩の方が速く、昔とは犠牲にしたいものが 逆になってしまった
  66. Green Tea🍵 • メモリ局所性の高い、新たなマークアルゴリズム ◦ Tri-colorを拡張し、スパンごとにオブジェクトを スキャンする • 実は名前の由来が日本 ◦

    Green Teaのプロトタイプを作ったのは、今のTech LeadであるAustine Clements ◦ プロトタイピングの大部分は、Austineさんが横浜 のカフェで大量の抹茶をしばきながら行った
  67. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  68. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  69. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  70. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  71. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  72. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  73. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  74. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  75. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  76. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  77. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  78. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  79. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  80. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  81. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  82. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  83. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  84. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  85. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  86. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  87. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  88. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  89. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  90. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  91. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  92. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  93. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  94. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  95. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  96. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  97. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  98. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  99. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  100. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  101. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  102. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  103. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  104. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  105. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  106. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  107. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T おさらい: ここから sweep phase
  108. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  109. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T T [4]*T [4]*T [4]*T
  110. スタック var x *T var y *T 状態一覧 見てない 見る予定

    今見てる もう見た スパンA スパンB スパンC スパンD T T T T T [4]*T [4]*T
  111. 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
  112. 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 これまでなら
  113. 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
  114. 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
  115. 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なら
  116. 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
  117. 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
  118. 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 こうなって欲しい (実際に確かめてはいません)