You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Erlang crash dump进程内存统计与proc段汇总值不一致问题咨询

问题原因说明

你遇到的统计差值本质是两个统计项的统计口径完全不同,不存在统计错误:

  • =memory段的processes/processes_used数值,是从Erlang进程专属堆分配器eheap_alloc(也就是崩溃日志里报错无法分配内存的那个分配器)的全局计数器直接读取的,统计的是该分配器从操作系统申请到的、划归进程私有内存池的所有内存总和。
  • =proc段每个进程条目下的Memory字段,统计的是每个存活进程当前正在使用的私有内存大小,包含进程栈、年轻代堆、老年代堆、已投递到进程的消息、进程控制块等已绑定到具体进程的内存。

两者的差值就是eheap_alloc持有但没有绑定到任何具体存活进程的内存,具体去向如下:

  • 分配器预留的空闲复用内存:这是差值的最主要来源。Erlang的堆分配器不会在进程GC、进程退出释放内存时立刻将内存归还给操作系统,而是会把空闲内存块留在对应调度器的内存载体(carrier)池中,供后续同调度器上的进程复用,避免频繁向OS申请/释放内存带来的性能损耗。如果应用之前出现过短时间的进程内存暴涨(比如处理大请求、消息短时间堆积),后续即使进程退出、GC回收了已使用内存,这部分预留的空闲内存依然会被算在processes_used统计中,但不会归属到任何存活进程的=proc记录下。结合你的场景差值超过75GB,这部分占比最高。
  • 崩溃时未完成记账的分配内存:崩溃触发点是进程正在申请3.9GB的堆内存,该请求发起时分配器已经将对应内存块从空闲池划入待分配状态,但还没完成绑定到目标进程的流程,crash dump生成时这部分内存不会被计入任何进程的Memory统计。
  • 未纳入进程Memory字段的进程关联内存:你使用的OTP版本开启了HiPE编译支持,HiPE模式下进程的native执行栈、进程关联的native代码私有缓存,在erts-11.1.1版本中不会被计入=proc段的Memory字段,但这部分内存本身是从eheap_alloc分配的,会被算入processes_used统计。此外还在调度器缓存队列中、尚未投递到目标进程的消息/信号,也属于这类未记账的进程私有内存。
  • 采集时间差带来的统计偏差:crash dump生成时,=memory段的全局分配器统计采集时间早于遍历所有进程生成=proc段的时间,STW(全进程暂停)阶段的内存释放操作可能导致两者统计存在小幅偏差,但这类偏差一般不会超过GB级别,不是你这个场景的主要原因。
验证与优化建议
  • 可以直接解析crash dump的=allocator段,找到eheap_alloc下所有载体的free字段总和,该值就是分配器持有的空闲预留内存,基本可以和你计算的差值匹配。
  • 排查=proc段中历史内存峰值最高的进程,重点关注消息队列长度、堆碎片数量、是否存在处理超大Erlang项的逻辑,确认之前内存暴涨的触发点。
  • 你当前使用的OTP23 erts-11.1.1版本的eheap_alloc在48核SMP场景下确实存在空闲内存归还策略过于保守的问题,尤其是跨调度器迁移进程时容易出现空闲内存堆积,可以通过调整VM启动参数+Mecs true开启空闲内存主动归还、+Mea min调整分配器策略降低预留内存比例,也可以升级到OTP23后续的补丁版本修复相关分配器问题。

补充说明:你的=memory统计中binary总占用仅221MB,可以排除大二进制泄漏导致的内存问题,故障根因确实在进程堆分配器的内存统计逻辑和预留策略上。

内容的提问来源于stack exchange,提问作者SilverBlaZe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 16:03:34