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

Go1.19から始めるGCのチューニング方法

 Go1.19から始めるGCのチューニング方法

芳賀壮

June 02, 2023
Tweet

Other Decks in Programming

Transcript

  1. |Go1.19から始めるGCのチューニング方法| | GOGCの役割 GOGC: GC頻度を操作する環境変数 使用ヒープメモリ量に対して、設定した割合分(GOGC) 新たに割り当てられた際にGCが実行される GC目標ヒープ量 = 使用ヒープ量

    + (使用ヒープ量 + GC始点) * GOGC / 100 ↓デフォルト(GOGC=100)の場合↓ GC目標ヒープ量 = 使用ヒープ量 *2 + α 8 GC root Target heap memory Live heap Live heap
  2. |Go1.19から始めるGCのチューニング方法| | GoのGCの仕組み(コンカレントマーク&スイープ方式) 17 Heap Root コンカレント GCがアプリケーションと並列に処理 → 処理が高速化(STWが短縮)

      → マーク漏れが生じる危険性 マーク漏れを防ぐ仕組み 色付ける(tri-color) 未探索: 白、探索中:グレー、探索終了:黒   ライトバリア 詳しくは、こちら
  3. |Go1.19から始めるGCのチューニング方法| mgc.go/gcStart() | Goのメモリ管理 18 sweep termination 前回GCのスイープ 処理の完了確認 _GCoff

    STW mark termination mark sweep _GCmark _GCmarktermination STW _GCoff STW マーク処理 マーク処理の完了 確認 スイープ処理のため 各種情報更新 スイープ処理 STW GCによりアプリケーションスレッドが止まる現象 _GChoge GCフェーズ
  4. |Go1.19から始めるGCのチューニング方法| mgc.go/gcStart() | Goのメモリ管理 19 sweep termination 前回GCのスイープ 処理の完了確認 _GCoff

    STW mark termination mark sweep _GCmark _GCmarktermination STW _GCoff STW マーク処理 マーク処理の完了 確認 スイープ処理のため 各種情報更新 スイープ処理 STW GCによりアプリケーションスレッドが止まる現象 _GChoge GCフェーズ
  5. |Go1.19から始めるGCのチューニング方法| | mark 20 _GCmark gcBgMark StartWorkers gcMark RootPrepare gcBgMark

    Prepare gcMark TinyAllocs マーク処理の本体 gcBgMarkWorkerの 起動関数 →ゴルーチンにより、 マルチスレッド処理さ れる gcBgMarkWorkerの ゴルーチン数と 待機数をカウント する値の初期化 マーク処理の始点 となるルート(root) の準備 スレッドごと保持し ている微小なメモリ 割り当て(tiny allocs)をマーク する処理
  6. |Go1.19から始めるGCのチューニング方法| | gcBgMarkWorker 21 gopark sleep gcMark Done gcDrain gcBgMarkWorker

    をキューに入れる 機構 マーク処理が必要 な時にすぐできる よう準備 マーク処理を行う 部分 参照できる オブジェクトを マークする mark phaseの 終了処理 ↓ sweep処理 _GCmark
  7. |Go1.19から始めるGCのチューニング方法| | gcBgMarkWorker 24 gopark sleep gcMark Done gcDrain gcBgMarkWorker

    をキューに入れる 機構 マーク処理が必要 な時にすぐできる よう準備 マーク処理を行う 部分。 参照できるオブ ジェクトをマーク する。 mark phaseの 終了処理 ↓ sweep処理 _GCmark
  8. |Go1.19から始めるGCのチューニング方法| | Goのメモリ管理 27 sweep termination _GCoff STW mark termination

    mark sweep _GCmark _GCmarktermination STW _GCoff STW gcStart gcBgMarkWorker gcDrain() gcMark Termination() gcSweep() gcBgMarkStartWorkers()
  9. |Go1.19から始めるGCのチューニング方法| | GCチューニング事例 検証環境 - アプリケーションサーバー - ECS on EC2

    (c6g.xlarge) - メモリ制限(ハードリミット):3GiB - RDS (common:t3.small, user:r5.xlarge) - Elasticache (cache.r6g.large × 2) 31
  10. |Go1.19から始めるGCのチューニング方法| | チューニング試験 3パターンで実施 32 パターン1 パターン2 パターン3 GOGC 100

    500 off GOMEMLIMIT - - 2700(3GiB) 備考 デフォルト 既存設定 GOMEMLIMIT導入 …, a good rule of thumb is to leave an additional 5-10% of headroom to account for memory sources the Go runtime is unaware of. (Goランタイムが認識できないメモリソースを考慮し、さらに5~10%のヘッドルームを残すのが良い経験則です。) 引用:A Guide to the Go Garbage Collector
  11. |Go1.19から始めるGCのチューニング方法| | チューニング結果 - パターン1 → パターン2 → パターン3の順で改善が見られる -

    GOMEMLIMITを取り入れたパターンが一番改善 33 パターン1 GOGC=100 パターン2 GOGC=500 パターン3 GOGC=off, MEMLIMIT=2700 RPS 最大値 1162 1347 1371 平均 1117 1290 1310 APIサーバー CPU使用率(最大) 385.84 379.57 377.14 NW IN(最大) 44.5 MiB/s 55.27 MiB/s 58.61MiB/s NW OUT(最大) 54.3 MiB/s 54.3 MiB/s 68.91 MiB/
  12. |Go1.19から始めるGCのチューニング方法| | チューニング結果 34 パターン1 GOGC=100 パターン2 GOGC=500 パターン3 GOGC=off,

    MEMLIMIT=2700 プロファイル GC総回数 8210 2263 510 GCで使用されるCPU割合 (gcBgMarkWorker) 10.22% 2.62% 1.0% ヒープ使用量 274MiB 769MiB 2604MiB - GOGCが大きいほどGC頻度が低い - GOGCが大きい→GCトリガー値が大きい→GC頻度が低い - GCで使用されるCPU割合も低い - GOMEMLIMITを取り入れたパターンはGC頻度が最も低い - 設定したヒープ上限(2700MiB)まで使用している
  13. |Go1.19から始めるGCのチューニング方法| While the memory limit is a powerful tool, ...,

    it's still important to use it thoughtfully. (メモリ制限は強力なツールであり、Goランタイムは誤用による最悪の挙動を軽減するための措 置を講じていますが、それでも思慮深く使用することが重要です。) Do take advantage of the memory limit when the execution environment of your Go program is entirely within your control, and the Go program is the only program with access to some set of resources. (メモリ制限を利用するのは、Goプログラムの実行環境が完全に自分のコントロール下にあり、 Goプログラムだけが何らかのリソース(コンテナのメモリ制限のような何らかのメモリ予約)に アクセスできる場合です。) 今回 - マシン上で実行するアプリケーションはGo製APIサーバーのみ - ECSのタスク定義より、コンテナ数・メモリ使用量を制限 | 考察 35 「A Guide to the Go Garbage Collector」 Suggested usesより 本環境がGOMEMLIMITの導入に適しており、検証結果からも有効性が見られる
  14. |Go1.19から始めるGCのチューニング方法| | まとめ GOGC/GOMEMLIMIT Go1.19よりGOMEMLIMITが導入 → メモリ上限をGCトリガーに設定可能 内部実装 マーク・スイープ処理を説明 チューニング事例

    Goプログラムの実行環境が制御可能であり、Goプログラムだけが リソースにアクセスできる場合であれば、GOMEMLIMITの導入の余地がある 36
  15. |Go1.19から始めるGCのチューニング方法| | 参考資料 A Guide to the Go Garbage Collector

    Go 1.19のメモリ周りの更新 GoのGC (garbage collector)について理解する 两万字长文带你深入Go语言GC源码 Goにおけるメモリ管理の可視化 37