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资讯^_^


查看所有标签

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

计算智能

计算智能

Russell C. Eberhart、Yuhui Shi / 人民邮电出版社 / 2009-2 / 69.00元

《计算智能:从概念到实现(英文版)》面向智能系统学科的前沿领域,系统地讨论了计算智能的理论、技术及其应用,比较全面地反映了计算智能研究和应用的最新进展。书中涵盖了模糊控制、神经网络控制、进化计算以及其他一些技术及应用的内容。《计算智能:从概念到实现(英文版)》提供了大量的实用案例,重点强调实际的应用和计算工具,这些对于计算智能领域的进一步发展是非常有意义的。《计算智能:从概念到实现(英文版)》取材......一起来看看 《计算智能》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换