한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

遊戲 Lag 白皮書 › L10 記憶體

記憶體洩漏 Memory leak

原因 ID mem-leak · 主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(伺服器基礎設施)

在含圖解與實驗的完整版中開啟卡片 →

沒有釋放的記憶體一點一點累積,幾天後演變成 GC 暴增、swap 或處理程序被強制終止。

為什麼 已登出角色的資料、事件處理常式(event handler)沒有被釋放 → 於是 可用記憶體在幾天內逐漸減少 → 畫面上 維護剛結束時一切正常,之後一天比一天 lag,最後伺服器當機

症狀
慢動作, 定格, 斷線
因素
停滯
誰會遇到
整個伺服器
何時
開越久越嚴重, 晚間尖峰時段
負責單位
主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(伺服器基礎設施)
遊戲開發團隊要做的事
分析 heap dump、進行長時間負載測試。
基礎設施團隊要做的事
監控各處理程序記憶體用量的趨勢並設定警示。
圖表上
緩慢爬升 · 處理程序記憶體(RSS)、GC 後的 heap
查看位置
以數天為單位觀察遊戲伺服器處理程序的記憶體(pidstat -r 的 RSS);有 GC 的伺服器則看 GC 剛結束時剩下的 heap。Java 看 -Xlog:gc 行中 GC 前後用量裡的 GC 後數值;.NET 看 dotnet-counters 的 GC 後 heap 大小(.NET 9 以後為 dotnet.gc.last_collection.heap.size,8 以下為 GC Heap Size)
符合的跡象
GC 剛結束時剩下的 heap(基線)在重新啟動後每天上升,人少的凌晨也不會降下來
不符合的跡象
heap 基線持平、只有 RSS 上升時,是碎片化(mem-fragment)或原生記憶體(native memory)的問題。隨人數起伏時是正常用量
確認方式
用基礎設施工具確認(不需要遊戲程式碼)
深入了解
如果每週定期維護都會重新啟動,洩漏就會被掩蓋,很久都不會被發現。常見的情況是某次維護延後,或活動讓人數增加時,問題才突然浮現。

出處

  1. Troubleshoot Memory Leaks Oracle
    執行越來越慢時要懷疑洩漏,最後記憶體耗盡而異常終止。分析洩漏的關鍵資料是 heap dump
  2. Debug a memory leak in .NET .NET
    即使有 GC,持續參考不再需要的物件也會造成洩漏,導致效能下降與 OutOfMemoryException。確認記憶體趨勢並分析 dump
  3. Garbage Collector Implementation Oracle
    -Xlog:gc 行的格式為「GC 前用量->GC 後用量(heap 大小)」
  4. dotnet-counters diagnostic tool .NET
    .NET 9 以後顯示為 dotnet.gc.last_collection.heap.size,.NET 8 以下顯示為 GC Heap Size
  5. pidstat(1) — Linux manual page sysstat
    -r:各處理程序的 RSS(實際位於 RAM 中的記憶體)與分頁錯誤

相關原因

同一層:L10 記憶體

同一症狀(慢動作)在其他層的原因

查看含圖解與實驗的完整版卡片