Fernando Simõesは、Go本番サービスで予期しない40msのガベージコレクタ停止に遭遇し、調査の結果、スワップ使用が根本原因であることが明らかになった。この問題は、2つのプロセスを含むcgroupで発生した。一方はio.ReadAllとproto.Unmarshalの操作を行い、blobおよびグラフ構造を作成するGoアプリケーション、もう一方はほとんどアイドル状態のHTTPサーバーである。”, “ガベージコレクション中、Goランタイムはストップ・ザ・ワールドの停止中にヒープ外にあるメタデータ構造を読み込む必要がある。Simõesは、メモリ圧力下ではカーネルのLRUベースのページェvictionによってこれらのメタデータページがスワップに移動されることを発見した。ガベージコレクタがこれらのページにアクセスしようとすると、各ページがメジャーページフォルトを引き起こし、カーネルはページテーブルエントリを読み込み、do_swap_pageを呼び出し、新しいフレームを割り当て、cgroupにチャージし、ページの内容を読み込み、bioリクエストを送信し、ディスクI/Oの完了を待ち、ページをメモリに復元する必要があった。”, “問題を診断するため、Simõesはストップ・ザ・ワールドイベント中のページフォルトを数えるBPFスクリプトを使用した。最悪の場合、40msの停止のうち39,902マイクロ秒がページフォルトによって消費されており、これは228回のフォルトで、フォルト処理に39,013マイクロ秒費やされていることを示していた。addr2lineの出力により、これらのフォルトはGCのブックキープ関数であるruntime.(*spanSet).reset、runtime.finishsweep_m、およびruntime.gcStart.func2にトレースされた。”, “ガベージコレクタは、スイープ終了とマーク終了の時点でストップ・ザ・ワールドの停止を行う。30分のテストでは、そのような停止が312回発生し、40msの遅延はメタデータがメモリに残っているときに観測された中央値の停止時間51マイクロ秒の800倍に相当した。各プロセッサ(P)がこれらの停止中に停止するため、I/Oを待つゴルーチンは完了信号を見逃す可能性があり、これが下流のレイテンシを引き起こす。”, “さらに、Simõesは511KiBのメッセージの構築時間がNVMeでは3-5msから105msに、Hetznerのネットワークボリュームでは903msに増加したことに言及したが、この遅延が同じスワップメカニズムによるものかどうかを確認することはできなかった。Go 1.26のGreen Teaガベージコレクタでテストしたアップデートでは、スワップ関連の停止問題への影響は無視できる程度だった。”, “プロット、モックアロケータ、BPFおよびPythonスクリプトを含む実験は、https://github.com/frnsimoes/go-gc-swap-cost で利用可能である。核心的な発見は変わらず、スワップとGoのガベージコレクタは低レイテンシワークロードに対して非互換であり、OSレベルのメモリ圧力がメタデータのページングを通じて制限のないストップ・ザ・ワールド停止を引き起こす可能性があるということである。”],