原Blog地址,http://www.linkedin.com/pulse/garbage-collection-erlang-tianpo-gao?trk=prof-post。
本文将简单的描述Erlang的垃圾回收,并不是深入的探讨。
在Erlang运行时环境中,Erlang进程采用复制分代回收的方式。分代垃圾回收将内存对象划分为不同的代。在Erlang运行时环境中,有两个代,年轻代和老年代。在Erlang的运行时环境中,内存回收主要有两种,一种叫做部分垃圾回收,另一种叫做全量垃圾回收。
在Erlang运行时环境中,每当进程的堆没有足够的空间去存储新的对象的时候,将会触发对该进程的垃圾回收。由于一个Erlang进程的堆栈上的数据不和其它Erlang进程共享,当Erlang进程终止执行的时候,并不会进行垃圾回收,而是直接交还给Erlang运行时环境。当发生垃圾回收的时候,进行垃圾回收的Erlang进程会被暂停,但是支持SMP的Erlang执行环境,会继续执行其它的Erlang进程,而不是整体暂停。在进行垃圾回收的时候,部分垃圾回收会先执行。全量垃圾回收会在执行一定次数的部分垃圾回收后执行,或者当部分垃圾回收无法释放出足够的空间时,全量垃圾回收也会被执行。
在执行部分垃圾垃圾回收时,垃圾回收器只对年轻代进行垃圾回收,并且将老年代移动到老年代专用堆中。当一个Erlang的Term经历了2到3个部分垃圾回收,那么这个Term将被提升到老年代。当进行全量回收的时候,垃圾回收器会对年轻代和老年代进行垃圾回收。
那么我们是如何将内存对象划分成不同的代的?在Erlang运行时环境中,Erlang进程的控制块PCB中有一个叫做high_water的字段。当一个存储在Erlang进程堆上的Term的地址比high_water存储的值要大,那么这个Term就是年轻代,反之就是老年代。
在Erlang运行时环境中,内存回收时暂停且复制的分代回收器。每次进行垃圾回收,都会创建出一个新的堆,当垃圾回收完成之后,Erlang进程原有的堆会被释放,并且新的堆将会成为当前Erlang进程的堆,当然原有堆中存活的数据将会被移动到新的堆中。