JavaScript垃圾回收

垃圾回收算法

1.标记清除算法

标记阶段:从根集合出发,将所有活动对象及其子对象打上标记
清除阶段:遍历堆,将非活动对象(未打上标记)的连接到空闲链表上

优点

实现简单, 容易和其他算法组合

缺点

碎片化, 会导致无数小分块散落在堆的各处
分配速度不理想,每次分配都需要遍历空闲列表找到足够大的分块
与写时复制技术不兼容,因为每次都会在活动对象上打上标记

2.引用计数 Reference Counting

引用计数,就是记录每个对象被引用的次数,每次新建对象、赋值引用和删除引用的同时更新计数器,如果计数器值为0则直接回收内存。 很明显,引用计数最大的优势是暂停时间短

优点

可即刻回收垃圾
最大暂停时间短
没有必要沿指针查找, 不要和标记-清除算法一样沿着根集合开始查找

缺点

计数器的增减处理繁重
计数器需要占用很多位
实现繁琐复杂, 每个赋值操作都得替换成引用更新操作
循环引用无法回收

3.分代回收

出发点:大部分对象生成后马上就变成垃圾,很少有对象能活的很久
新生代 = 生成空间 + 2 * 幸存区 复制算法

老年代 标记-清除算法

对象在生成空间创建,当生成空间满之后进行 minor gc,将活动对象复制到第一个幸存区,并增加其“年龄” age,当这个幸存区满之后再将此次生成空间和这个幸存区的活动对象复制到另一个幸存区,如此反复,当活动对象的 age 达到一定次数后将其移动到老年代; 当老年代满的时候就用标记-清除或标记-压缩算法进行major gc
吞吐量得到改善, 分代垃圾回收花费的时间是GC复制算法的四分之一;但是如果部分程序新生成对象存活很久的话分代回收会适得其反