标签:
作者: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}])
先看下参数默认值: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标签:
原文地址:http://my.oschina.net/u/658658/blog/420124