v8的垃圾回收机制(二)

理解垃圾回收机制有助于理解闭包,内存释放,和内存溢出的知识。


1

Mark-Sweep & Mark-Compact


对于老生代中的对象,由于存活对象占较大比重,再采用Scavenge的方式会有两个问题:一个是存活对象较多,复制存活对象的效率将会很低;另一个问题依然是浪费一半空间的问题。这两个问题导致应对生命周期较长的对象时Scavenge会显得捉襟见肘。为此,V8在老生代中主要采用了Mark-Sweep和Mark-Compact相结合的方式进行垃圾回收。


Mark-Sweep是标记清除的意思,它分为标记和清除两个阶段。与Scavenge相比,Mark-Sweep并不将内存空间划分为两半,所以不存在浪费一半空间的行为。与Scavenge复制活着的对象不同,Mark-Sweep在标记阶段遍历堆中的所有对象,并标记活着的对象,在随后的清除阶段中,只清除没有被标记的对象。可以看出,Scavenge中只复制活着的对象,而Mark-Sweep只清理死亡对象。活对象在新生代中只占较小部分,死对象在老生代中只占较小部分,这是两种回收方式能高效处理的原因。


v8的垃圾回收机制(二)

Mark-Sweep最大的问题是在进行一次标记清除回收后,内存空间会出现不连续的状态。这种内存碎片会对后续的内存分配造成问题,因为很可能出现需要分配一个大对象的情况,这时所有的碎片空间都无法完成此次分配,就会提前触发垃圾回收,而这次回收是不必要的。


为了解决Mark-Sweep的内存碎片问题,Mark-Compact被提出来。Mark-Compact是标记整理的意思,是在Mark-Sweep的基础上演变而来的。它们的差别在于对象在标记为死亡后,在整理的过程中,将活着的对象往一端移动,移动完成后,直接清理掉边界外的内存。


v8的垃圾回收机制(二)


完成移动后,就可以直接清除最右边的存活对象后面的内存区域完成回收。


这里将Mark-Sweep和Mark-Compact结合着介绍不仅仅是因为两种策略是递进关系,在V8的回收策略中两者是结合使用的。


在Mark-Sweep和Mark-Compact之间,由于Mark-Compact需要移动对象,所以它的执行速度不可能很快,所以在取舍上,V8主要使用Mark-Sweep,在空间不足以对从新生代中晋升过来的对象进行分配时才使用Mark-Compact。


v8的垃圾回收机制(二)

相关文章: