ゲームラグ白書 › L10 メモリ
GCスラッシング(ヒープの空き不足) GC thrashing (heap nearly full)
原因ID mem-gc-thrash · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ
図と実験のあるメインページでこのカードを開く →
生存データがヒープの上限に近づくと、GCが走っても回収できるものがほとんどなく、GCが休みなく繰り返されます。
なぜ イベントでの人数増加やリークで、生存データがヒープの上限近くまで埋まる → すると GCがわずかしか回収できず、すぐにまたFull GC、CPUの大半をGCが使う → 画面では サーバー全体が数分間スローモーション・フリーズを繰り返し、メモリ不足で終了
症状 スローモーション , フリーズ , 切断
要因 ストール
誰に起きるか サーバー全体
いつ 夜のピーク時間帯, 人が集中したとき, 長時間稼働するほど
担当 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ
ゲーム開発チームの対応 ヒープをピーク時の生存データより余裕をもって(通常2倍以上)設定、長く参照し続けるデータ・リークの削減。
インフラチームの対応 GC時間比率のアラート、粘らずに早めに再起動、ヒープを増やせるようメモリに余裕のあるインスタンス。
数値の目安 実行時間の10%を超えてGCに使っていれば、一般に危険信号とみなします。Javaの一部のGCは、時間の98%をGCに費やしてもほとんど回収できないとメモリ不足のエラーを出します。
グラフでは 上限で頭打ち · GC直後のヒープ、GC時間比率
確認箇所 GC直後に残ったヒープが最大ヒープにどれだけ近いかと、GCに使った時間の比率を確認。Javaは-Xlog:gcの行の「GC後(ヒープサイズ)」とPause Full行の頻度、.NETはdotnet-counters(.NET 8以前は% Time in GC since last GC、.NET 9以降はdotnet.gc.pause.timeの増加量)、GoはGODEBUG=gctrace=1の行と行の間隔を確認 該当する場合 GC直後もヒープが最大値近くまで残り、Full GCが立て続けに走り、GC時間比率が普段より大きく(通常10%超)上がる。その間サーバー全体のティックがそろって遅くなる 該当しない場合 GC直後のヒープに余裕があるのに停止だけが長いなら、GC方式・設定側(mem-gc) 確認手段 インフラのツールで確認(ゲームコード不要)
出典 The Parallel Collector Oracle パラレルGCは全体時間の98%超をGCに費やしてもヒープの回収が2%未満だとOutOfMemoryError Garbage-First Garbage Collector Tuning Oracle G1はデフォルト(GCTimeRatio=12)でGC時間を全体の約8%以下に抑えるようヒープサイズを決める、ヒープ占有率が高すぎて起きたFull GCはログのPause Full (G1 Compaction Pause)で見つける A Guide to the Go Garbage Collector Go デフォルトのGOGC=100では目標ヒープが生存ヒープの約2倍、メモリ上限に張り付くとGCが休みなく走るスラッシング、GODEBUG=gctrace=1でGCトレースを出力 Garbage Collector Implementation Oracle -Xlog:gcの行はGCの種類(Pause Young、Pause Full)と「GC前の使用量->GC後の使用量(ヒープサイズ)」、停止時間 dotnet-counters diagnostic tool .NET .NET 9以降はdotnet.gc.pause.time、.NET 8以前は% Time in GC since last GCで表示
あわせて読みたい原因
同じ層:L10 メモリ
同じ症状(スローモーション)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る