ゲームラグ白書 › L10 メモリ
メモリリーク Memory leak
原因ID mem-leak · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ
図と実験のあるメインページでこのカードを開く →
解放されないメモリが少しずつたまり、数日後にGCの多発・スワップ・強制終了につながります。
なぜ ログアウトしたキャラクターの情報・イベントハンドラーが解放されない → すると 数日かけて空きメモリが減っていく → 画面では メンテ明けは正常、日を追うごとにラグが増え、最後はサーバーダウン
- 症状
- スローモーション, フリーズ, 切断
- 要因
- ストール
- 誰に起きるか
- サーバー全体
- いつ
- 長時間稼働するほど, 夜のピーク時間帯
- 担当
- 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ
- ゲーム開発チームの対応
- ヒープダンプの解析、長時間の負荷テスト。
- インフラチームの対応
- プロセスごとのメモリ使用量の推移の監視とアラート。
- グラフでは
- 徐々に上昇 · プロセスのメモリ(RSS)、GC直後のヒープ
- 確認箇所
- ゲームサーバープロセスのメモリ(pidstat -rのRSS)を数日単位で確認し、GCを使うサーバーはGC直後に残ったヒープを確認。Javaは-Xlog:gcの行に出るGC前・後の使用量のうちGC後の値、.NETはdotnet-countersのGC後のヒープサイズ(.NET 9以降はdotnet.gc.last_collection.heap.size、8以前はGC Heap Size)
- 該当する場合
- GC直後に残るヒープ(ベースライン)が再起動後に日ごとに上がり、人数の少ない早朝にも下がらない
- 該当しない場合
- ヒープのベースラインは横ばいなのにRSSだけ上がるなら、断片化(mem-fragment)かネイティブメモリ側。人数に連動して上下するなら正常な使用量
- 確認手段
- インフラのツールで確認(ゲームコード不要)
- もっと詳しく
- 定期メンテで毎週再起動していると、リークが隠れて長い間見つかりません。メンテが一度延期されたときや、イベントで人数が増えたときに突然表面化することがよくあります。
出典
- Troubleshoot Memory Leaks Oracle
実行が徐々に遅くなるならリークを疑う、最終的にメモリが尽きて異常終了。リーク解析の中心となる資料はヒープダンプ - Debug a memory leak in .NET .NET
GCがあっても不要なオブジェクトを参照し続けるとリーク、性能低下とOutOfMemoryException。メモリの推移の確認とダンプの解析 - Garbage Collector Implementation Oracle
-Xlog:gcの行は「GC前の使用量->GC後の使用量(ヒープサイズ)」の形式 - dotnet-counters diagnostic tool .NET
.NET 9以降はdotnet.gc.last_collection.heap.size、.NET 8以前はGC Heap Sizeで表示 - pidstat(1) — Linux manual page sysstat
-r:プロセスごとのRSS(実際にRAM上にあるメモリ)とページフォルト
あわせて読みたい原因
同じ層:L10 メモリ
同じ症状(スローモーション)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る