Erlang进程堆垃圾回收机制

标签: erlang 进程 垃圾回收 | 发表时间:2014-05-23 08:17 | 作者:cwqcwk1
出处:http://blog.csdn.net

原文: Erlang进程堆垃圾回收机制

作者:http://blog.csdn.net/mycwq

每个Erlang进程创建之后都会有自己的PCB,栈,私有堆。erlang不知道他创建的进程会用到哪种场合下,所以一开始分配的内存比较小。如果分配的空间不够了,erlang gc会动态调整堆大小以满足需求,如果分配的空间大了,就会收缩堆,回收内存。

erlang进程堆的gc是分代gc,分代gc的想法基于统计学:大部分数据的生存周期都比较短,最新的数据更容易不再被使用。这里erlang使用young heap 和old heap来区分数据,young heap放新数据,old heap放旧数据,也就是gc后存活的数据。

erlang进程堆gc有两个主要过程:浅扫描和深扫描

浅扫描(minor collection)

浅扫描是当young heap空间不足时,erlang会对young heap做一次扫描,把有用的数据复制到新申请的young heap空间,发现已经扫描过1次以上的数据放入old heap,然后删掉原来的young heap

在young heap中,erlang使用了高水位线来区分标记一次以上的数据和未标记的数据,那么young heap移入old heap的就是超过高水位线的数据

深扫描(major collection)

深扫描是一般当old heap空间不足时触发,erlang会对young heap和old heap做扫描,把有用的数据放入新申请的young heap,删掉原来的heap

深扫描的触发条件还有手动执行gc,和gc次数超过fullsweep_after的参数限定



控制垃圾回收

以游戏网关进程为例,网关进程通常有大量消息,而大部分消息都只是在网关这里做转发,生命周期很短,所以网关进程可以设定较大的初始内存,较快的内存回收。

spawn_opt(Fun, [{min_heap_size, 5000},{min_bin_vheap_size, 100000},{fullsweep_after, 500}])

先看下参数默认值:
1> erlang:system_info(min_heap_size).
{min_heap_size,233}
2> erlang:system_info(min_bin_vheap_size).
{min_bin_vheap_size,46368}
3> erlang:system_info(fullsweep_after).
{fullsweep_after,65535}

min_heap_size是进程最小堆大小

这个参数两个地方会用到,第一处是erlang初始化进程堆大小,第二处是gc后堆收缩后维持的最小值,min_bin_vheap_size是进程最小虚拟二进制堆大小,这两个参数都是以word为单位。初始化足够大的初始内存,可以减少轻度gc的次数,减少反复申请和回收内存的开销

fullsweep_after控制深扫描的频率

这个参数确定多少次gc后执行一次深度gc,默认值为65536,有点大了

所以,上面3个参数配合起来的意义就是,进程初始化分配足够大的内存,减少反复申请内存的开销,当申请的内存不够用,gc会重新申请内存,累计达到500次就做一次gc


手动执行垃圾回收

上面提到了利用fullsweep_after来控制gc的情况,下面再介绍手动gc的情况:
在rabbitMQ看到这段代码,可以在项目中定期执行这个函数:
gc() ->
    [erlang:garbage_collect(P) || P <- erlang:processes(),
                           {status, waiting} == erlang:process_info(P, status)],
    erlang:garbage_collect(),
    ok.
当然,你还可以加入一些判断,比如指定占内存过50M的进程执行gc

erlang进程占用多少内存

用下面这个方法检查erlang进程占用的内存,你可以换别的参数再试试
Fun = fun()-> receive after infinity -> ok end end.
erlang:process_info(erlang:spawn(Fun), memory).

erlang垃圾回收的副作用

前面讲到erlang进程堆的gc是分代gc的,这个只是全局层面的,在底层erlang还是走了标记清除的路子。标记清除这种gc方式是定期执行的,首先gc不够及时,其次,在gc执行期间开销比较大,会引起中断。不过每个erlang进程的堆区域是独立的,gc可以独立进行,加上它内存区域比较小,还有erlang的变量是单次赋值,无需多次追踪,因此,erlang进程gc的延迟不会引起全局的中断

erlang文档 参考
GC in Erlang works independently on each Erlang process, i.e. each Erlang process has its own heap, and that heap is GCed independently of other processes' heaps.
The current default GC is a "stop the world" generational mark-sweep collector. On Erlang systems running with multiple threads (the default on systems with more than one core), GC stops work on the Erlang process being GCed, but other Erlang processes on other OS threads within the same VM continue to run. The time the process spends stopped is normally short because the size of one process' heap is normally relatively small; much smaller than the combined size of all processes heaps.

结束语

这里讲了erlang进程堆的gc,另外erlang还有其他gc机制,比如,二进制共享堆和进程外堆碎片是引用计数gc,这里先不做讨论,有时间我会在下篇做讨论,有兴趣可以看 这里了解一下。


参考:

http://blog.csdn.net/mycwq/article/details/26613275

http://www.cnblogs.com/me-sa/archive/2011/11/13/erlang0014.html

作者:cwqcwk1 发表于2014-5-23 0:17:52 原文链接
阅读:30 评论:0 查看评论

相关 [erlang 进程 垃圾回收] 推荐:

Erlang进程堆垃圾回收机制

- - CSDN博客推荐文章
原文: Erlang进程堆垃圾回收机制. 作者:http://blog.csdn.net/mycwq. 每个Erlang进程创建之后都会有自己的PCB,栈,私有堆. erlang不知道他创建的进程会用到哪种场合下,所以一开始分配的内存比较小. 如果分配的空间不够了,erlang gc会动态调整堆大小以满足需求,如果分配的空间大了,就会收缩堆,回收内存.

jvm垃圾回收

- Cano - 淘宝共享数据平台 tbdata.org
在jvm中堆空间划分为三个代:年轻代(Young Generation)、年老代(Old Generation)和永久代(Permanent Generation). 年轻代和年老代是存储动态产生的对象. 永久带主要是存储的是java的类信息,包括解析得到的方法、属性、字段等等. 我们这里讨论的垃圾回收主要是针对年轻代和年老代.

JVM 垃圾回收算法

- - 码蜂笔记
《深入理解Java虚拟机:JVM高级特性与最佳实践》-笔记. 垃圾回收,Garbage Collection,简称GC. 判断对象是否存活一般有两种方式:. 引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收. 此方法简单,无法解决对象相互循环引用的问题.

Java中的垃圾回收

- - Java译站
前文中对标记删除算法的介绍更多还是偏理论性质的. 实践中,为了更好地满足现实的场景及需求,还需要对算法进行大量的调整. 举个简单的例子,我们来看下JVM需要记录哪些信息才能让我们得以安全地分配对象空间. 碎片及整理(Fragmenting and Compacting). JVM在清除不可达对象之后,还得确保它们所在的空间是可以进行复用的.

Java垃圾回收调优

- - 编程语言 - ITeye博客
在Java中,通常通讯类型的服务器对GC(Garbage Collection)比较敏感. 通常通讯服务器每秒需要处理大量进出的数据包,需要解析,分解成不同的业务逻辑对象并做相关的业务处理,这样会导致大量的临时对象被创建和回收. 同时服务器如果需要同时保存用户状态的话,又会产生很多永久的对象,比如用户session.

谈谈ActionScript垃圾回收(下)

- Tomyail - Kevin Cao&#39;s Blog
前文我们介绍了GC的工作机制和帮助GC更好工作的最佳实践. 其实只要我们遵守谁创建谁清理的原则来管理对象,就能基本上避免回收失败,也就是我们通常说的内存泄漏问题. 但是在实际项目中我们还会看到各种原因引起的内存泄漏,接下来就让我们一起来找出病因. 首先我们需要观察症状,也就是内存的使用曲线. 排查的方法是反复执行一些创建和删除对象的方法、反复加载和卸载子文件.

谈谈ActionScript垃圾回收(上)

- Jia - Kevin Cao&#39;s Blog
在《给AS程序员的一点建议一文》中我提到了释放资源的重要性. 最近在一些项目过程中我又对这方面有了更多的理解,在此希望能够分享给大家. 首先让我们来回顾一下关于垃圾回收(Garbage Collection,下文简称GC)的一些知识. 要阅读本文,你需要对GC机制有些基本认识. 在ActionScript中,我们没有API可以直接删除一个对象,也不能控制Player进行GC.

JVM垃圾回收(GC)原理

- kill - yiihsia[互联网后端技术]_yiihsia[互联网后端技术]
引用计数(Reference Counting). 原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数. 垃圾回收时,只用收集计数为0的对象. 此算法最致命的是无法处理循环引用的问题. 标记-清除(Mark-Sweep). 第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除.

HotSpot 垃圾回收算法实现

- - 码蜂笔记
《深入理解Java虚拟机:JVM高级特性与最佳实践》-笔记. 在可达性分析期间整个系统看起来就像被冻结在某个时间点上,不可以出现分析过程中对象引用关系还在不断变化的情况. 一致性要求导致GC进行时必须停顿所有Java执行线程. 即使在号称不会发生停顿的CMS收集器中,枚举根节点时也是必须停顿的. HotSpot使用的是准确式GC,当执行系统停顿下来后,并不需要一个不漏地检查完所有执行上下文和全局的引用位置,这是通过一组称为OopMap的数据结构来达到的.