做者:http://blog.csdn.net/mycwq html
每一个Erlang进程建立以后都会有本身的PCB,栈,私有堆。erlang不知道他建立的进程会用到哪一种场合下,因此一开始分配的内存比较小。若是分配的空间不够了,erlang gc会动态调整堆大小以知足需求,若是分配的空间大了,就会收缩堆,回收内存。 ide
erlang进程堆的gc是分代gc,分代gc的想法基于统计学:大部分数据的生存周期都比较短,最新的数据更容易再也不被使用。这里erlang使 用young heap 和old heap来区分数据,young heap放新数据,old heap放旧数据,也就是gc后存活的数据。 函数
erlang进程堆gc有两个主要过程:浅扫描和深扫描 ui
浅扫描(minor collection) spa
浅扫描是当young heap空间不足时,erlang会对young heap作一次扫描,把有用的数据复制到新申请的young heap空间,发现已经扫描过1次以上的数据放入old heap,而后删掉原来的young heap .net
在young heap中,erlang使用了高水位线来区分标记一次以上的数据和未标记的数据,那么young heap移入old heap的就是超太高水位线的数据 orm
深扫描(major collection) htm
深扫描是通常当old heap空间不足时触发,erlang会对young heap和old heap作扫描,把有用的数据放入新申请的young heap,删掉原来的heap blog
深扫描的触发条件还有手动执行gc,和gc次数超过fullsweep_after的参数限定 生命周期
控制垃圾回收
以游戏网关进程为例,网关进程一般有大量消息,而大部分消息都只是在网关这里作转发,生命周期很短,因此网关进程能够设定较大的初始内存,较快的内存回收。spawn_opt(Fun, [{min_heap_size, 5000},{min_bin_vheap_size, 100000},{fullsweep_after, 500}])
先看下参数默认值:min_heap_size是进程最小堆大小
这个参数两个地方会用到,第一处是erlang初始化进程堆大小,第二处是gc后堆收缩后维持的最小值,min_bin_vheap_size是进 程最小虚拟二进制堆大小,这两个参数都是以word为单位。初始化足够大的初始内存,能够减小轻度gc的次数,减小反复申请和回收内存的开销
fullsweep_after控制深扫描的频率
这个参数肯定多少次gc后执行一次深度gc,默认值为65536,有点大了
因此,上面3个参数配合起来的意义就是,进程初始化分配足够大的内存,减小反复申请内存的开销,当申请的内存不够用,gc会从新申请内存,累计达到500次就作一次gc
手动执行垃圾回收
上面提到了利用fullsweep_after来控制gc的状况,下面再介绍手动gc的状况:erlang进程占用多少内存
用下面这个方法检查erlang进程占用的内存,你能够换别的参数再试试前面讲到erlang进程堆的gc是分代gc的,这个只是全局层面的,在底层erlang仍是走了标记清除的路子。标记清除这种gc方式是按期执行 的,首先gc不够及时,其次,在gc执行期间开销比较大,会引发中断。不过每一个erlang进程的堆区域是独立的,gc能够独立进行,加上它内存区域比较 小,还有erlang的变量是单次赋值,无需屡次追踪,所以,erlang进程gc的延迟不会引发全局的中断
erlang文档 参考结束语
这里讲了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