GoのGCがスワップで40ms停止、原因はメタデータのページフォルト

A 40ms Go garbage collector pause caused by swap

GoのGCがスワップで40ms停止、原因はメタデータのページフォルト

Goのガベージコレクタはstop-the-world中にヒープ外のメタデータを読むが、そのページがスワップに追い出されていると、ページフォルトが発生し、40msもの停止を引き起こす。HetznerのNVMe上で計測したところ、中央値51usの停止が最大40msに達し、そのうち39msは228回のページフォルトに費やされていた。スワップ自体は悪ではないが、GCとの相性が悪いことを示す実測結果だ。

40msは中央値の800倍だ。テスト中のメモリスパイクで2、3回発生する。これは大きい。
  1. nasretdinov

    残念ながら、それはある程度予想されることだ。実装がどうであれ、GCが参照されている部分をトレースするためにツリー全体を何らかの形で走査する必要があるという事実だけでも、swapは極めて非実用的になる。たとえ40msのstop-the-worldポーズがなかったとしても、swapが使うLRUキャッシュはGCのたびに捨てられてしまうだろう。

    AppleがフレームワークでGCをやめて自動参照カウント方式に切り替えたのも、実は同じ理由だと思う。

  2. jacobgold

    「これをやると痛いんだ」

    「やめろよ」

    レイテンシが気になるなら、swapを無効にしよう。システム全体で、あるいは特定のcgroupで。

  3. pizlonator

    GoがオンザフライGC、つまりSTWが全くない方式を使わない理由でもあるのか?

  4. xavdid

    Discordは2020年にこれを学んで、素晴らしいブログ記事を公開している:https://discord.com/blog/why-discord-is-switching-from-go-to...

  5. soltanov

    GCレイテンシのSLOには、オペレーティングシステムのメモリプレッシャーを含めるべきだ。そうでなければ、ページフォルトの問題がコレクタの問題に見えてしまい、間違った修正につながる。

  6. Gabrys1

    swapを意識したGCというのはあり得るのだろうか、たとえばまず必要なページをswapインして(そんな明白なAPIがあるわけではないが…)、それからworldを止めるとか?

  7. imclaren

    これだよ。Goではメモリ肥大化のバグは比較的簡単に直せるが、swapの肥大化を解消するのは時に冒険になる。そしてswapの肥大化は全部解消する価値があると思う!

  8. faangguyindia

    Node、Ruby、Pythonを使うようなところではGoを使う。

    低レイテンシが必要なところではRustを使う。

この日のほかの記事

2026-10-05