2.3 垃圾回收机制

99 阅读2分钟

我们知道js是自动回收垃圾,这一切是由v8的两个垃圾回收器去实现的,那v8是如何实现垃圾回收的?

一、垃圾回收器如何工作?

1、垃圾回收算法
1.1 首先通过GC Root标记空间中活动对象(gc root可遍历访问的对象)和非活动对象(gc root不可遍历访问的对象
1.2 回收非活动对象所占用的内存
1.3 内存整理,内存回收后对产生不连续的内存碎片进行整理

2、v8带有两个垃圾回收器
2.1 主回收器
特点:老生代的垃圾回收器、容量大、存活时间长
垃圾回收步骤:
1、标记清除算法(mark sweep)
image.png
2、标记整理(mark compart)
image.png

2.2 副回收器
特点:新生代的垃圾回收器、容量小1~8M、存活时间短 回收步骤: 1、采用Scavenge 算法,分成对象区和空闲区两个区
image.png

2、新加入的对象都放到对象区,在区域满的时候触发垃圾回收,将标记好的活动对象移动到空闲区并且整理 image.png

3、对象区和空闲区进行角色反转,意思是将两边数据进行交换,对象区就有空闲区整理好的活动对象,空闲区又带有对象区的垃圾数据
image.png

优化策略: 随着新生区容量小,会频繁触发垃圾回收机制,如果在新生区超过两次垃圾回收都是活动的对象,那么v8采用对象普升策略,将该新生区的对象放到老生区

二、如何优化垃圾回收的执行效率

背景:垃圾回收会占用主线程资源,需要考虑如何合理安排垃圾回收
方案:垃圾回收主要采用并行、并发、增量垃圾回收技术 思考:从两个维度思考,1、将垃圾回收拆分成多个小的任务,减少执行占用时间过长;2、将标记和整理活动对象任务放到后台线程去整理

1、并行回收,开启多个辅助线程进行垃圾标记清理,副垃圾回收器采用该方式 image.png

2、增量回收,每次执行垃圾回收在主线程穿插很小部分执行,其中运用到增量标记算法(标记当前垃圾回收对象所处位置,方便下次任务从该位置继续执行) image.png

3、并发回收,开启多个辅助线程在后台完成垃圾回收,不阻塞主线程任务执行,执行效率高(主垃圾回收器用得多) image.png

实际v8采用三种方式执行垃圾回收,如下所示

image.png 从图中可以看出标记任务都是在辅助线程完成,主线程只采用增量标记穿插执行清除整理垃圾任务