Erlang 内存问题诊断

栏目: Erlang · 发布时间: 3年前

来源: wudaijun.com

内容简介:Erlang 内存问题诊断

本文转载自:http://wudaijun.com/2016/12/erlang-memory-debug/?utm_source=tuicool&utm_medium=referral,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

通过 erlang:memory() 查看节点内存占用总览,需要通过静态和动态两个维度对内存进行考核:

  • 静态: 各类内存占用比例,是否有某种类的内存占用了节点总内存的绝大部分
  • 动态: 各类内存增长特性,如增长速度,或是否长期增长而不回收(atom除外)

找出有疑似内存泄露的种类后,再进行下一步分析

atom

atom不会被GC,这意味着我们应该对atom内存增长更加重视而不是忽略。在编写代码时,尽量避免动态生成atom,因为一旦你的输入源不可靠或受到攻击(特别针对网络消息),atom内存增长可能导致节点crash。可以考虑将atom生成函数替换为更安全的版本:

list_to_atom/1 -> list_to_existing_atom/1
binary_to_atom/2 -> binary_to_existing_atom/2
binary_to_term(Bin) -> binary_to_term(Bin,[safe])

ets

ets内存占用通常是由于表过大,通过 ets:i(). 查看ets表条目数,大小,占用内存等。

process

进程内存占用过高可能有两方面原因,进程数量过大和进程占用内存过高。针对于前者,首先找出那些没有被链接或监控的”孤儿进程”:

[P || P<-processes(),
    [{_,Ls},{_,Ms}] <- [process_info(P,[links,monitors])],
    []==Ls,[]==Ms].

或通过 supervisor:count_children/1 查看sup下进程数量和状态。

而如果是进程所占内存过高,则可将内存占用最高的几个进程找出来进行检查:

recon:proc_count(memory, 10). % 打印占用内存最高的10个进程
recon:proc_count(message_queue_len, 10). % 打印消息队列最长的10个进程

binary

erlang binary大致上分为两种,heap binary(<=64字节)和refc binary(>64字节),分别位于进程堆和全局堆上,进程通过ProBin持有refc binary的引用,当refc binary引用计数为0时,被GC。关于binary的详细实现,参考 Erlang常用数据结构实现

recon提供的关于binary问题检测的函数有:

% 打印出引用的refc binary内存最高的N个进程
recon:proc_count(binary_memory, N)
% 对所有进程执行GC 打印出GC前后ProcBin个数减少数量最多的N个进程
recon:bin_leak(N)

以上两个函数,通常可以找出有问题的进程,然后针对进程的业务逻辑和上下文进行优化。通常来说,针对于refc binary,有如下思路:

  • 每过一段时间手动GC(高效,不优雅)
  • 如果只持有大binary中的一小段,用 binary:copy/1-2 (减少refc binary引用)
  • 将涉及大binary的工作移到临时一次性进程中,做完工作就死亡(变相的手动GC)
  • 对非活动进程使用hibernate调用(该调用将进程挂起,执行GC并清空调用栈,在收到消息时再唤醒)

一种典型地binary泄露情形发生在当一个生命周期很长的中间件当作控制和传递大型refc binary消息的请求控制器或消息路由器时,因为ProcBin仅仅只是个引用,因此它们成本很低而且在中间件进程中需要花很长的时间去触发GC,所以即使除了中间件其他所有进程都已经GC了某个refc binary对应的ProcBin,该refc binary也需要保留在共享堆里。因此中间件进程成为了主要的泄漏源。

针对这种情况,有如下解决方案:

  • 避免中间件接触到refc binary,由中间件进程返回目标进程的Pid,由原始调用者来进行binary转发
  • 调整中间件进程的GC频率(fullsweep_after)

driver/nif

另一部分非Erlang虚拟机管制的内存通常来自于第三方Driver或NIF,要确认是否是这部分内存出了问题,可通过 recon_alloc:memory(allocated). 和OS所报告的内存占用进行对比,可以大概得到C Driver或NIF分配的内存,再根据该部分内存的增长情况和占用比例来判断是否出现问题。

如果是纯C,那么内存使用应该是相对稳定并且可预估的,如果还挂接了 Lua 这类动态语言,调试起来要麻烦一些,在我们的 服务器 中,Lua部分是无状态的,可以直接重新加载Lua虚拟机。其它的调试手段,则要透过Lua层面的GC机制去解决问题了。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

关注码农网公众号

关注我们,获取更多IT资讯^_^


查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ordering Disorder

Ordering Disorder

Khoi Vinh / New Riders Press / 2010-12-03 / USD 29.99

The grid has long been an invaluable tool for creating order out of chaos for designers of all kinds—from city planners to architects to typesetters and graphic artists. In recent years, web designers......一起来看看 《Ordering Disorder》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具