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

游戏卡顿白皮书 › L10 内存

内存泄漏 Memory leak

原因 ID mem-leak · 主责 研发团队·服务器开发 · 配合 运维团队·系统运维

在含图示和实验的完整版中打开此卡片 →

没有释放的内存一点点累积,几天后引发 GC 失控、swap 或进程被强制终止。

起因 已下线角色的数据、事件处理函数没有释放 → 结果 空闲内存在几天内持续减少 → 画面表现 维护结束后正常,越往后越卡,最终服务器宕机

症状
慢动作, 卡住, 掉线
因素
停顿
谁会遇到
全服
何时出现
开得越久越严重, 晚高峰
负责方
主责 研发团队·服务器开发 · 配合 运维团队·系统运维
研发团队要做的事
分析堆 dump,长时间压测。
运维团队要做的事
监控各进程内存占用的趋势并设置告警。
监控图上
缓慢爬升 · 进程内存(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)或原生内存。随人数起伏则是正常占用
确认手段
运维工具即可确认(无需游戏代码)
深入了解
每周例行维护都会重启,泄漏因此被掩盖,很长时间都发现不了。往往在某次维护推迟、或活动带来人数增加时突然暴露。

出处

  1. Troubleshoot Memory Leaks Oracle
    运行越来越慢时应怀疑泄漏,最终内存耗尽而异常退出。分析泄漏的关键材料是堆 dump
  2. Debug a memory leak in .NET .NET
    即使有 GC,一直引用不再需要的对象也会泄漏,导致性能下降和 OutOfMemoryException。做法是查看内存趋势并分析 dump
  3. Garbage Collector Implementation Oracle
    -Xlog:gc 行的格式为“GC 前占用->GC 后占用(堆大小)”
  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(实际驻留在物理内存中的部分)和缺页(page fault)

相关原因

同一层:L10 内存

其他层中同样导致“慢动作”的原因

查看含图示和实验的原卡片