关于V8的垃圾回收机制
看过掘金一位小姐姐写的关于V8引擎-垃圾回收的文章(末尾附上链接),大致总结垃圾回收的执行机制主要是以下3个步骤:
- 首先遍历对象,标记不可访问的对象表示可以被回收。
- 标记完成后回收被标记可以被回收的对象
- 内存整理(就是整理内存碎片,释放大的连续的内存空间)
在回收过程中然后又分为了2种不同的回收情况:
- 老生代区域-存放生存时间长的对象(主回收器回收)
- 新生代区域-存放生存时间短的对象(副回收器回收)
简单点讲就是:
- 主回收器负责回收占用内存较大的对象,回收频率不是那么的高
- 副回收器负责回收占用内存较小的对象,回收频率比较频繁
不同的回收器回收的区域,对象不一样,频率不同,那么他们回收的过程肯定也是不同的:
- 副回收器
回收的区域是新生代的区域,该区域又分为对象区和空闲区,新加入的对象都会存放到对象区域,当对象区域快被写满时,就需要执行一次垃圾清理操作。
回收过程中还是先标记需要回收的对象,标记完之后将不需要回收的对象拷贝一份放到空闲区,并且有序地进行排列,这样就相当于还进行了内存整理。然后
将空闲区变为对象区,然后清理空闲区就可以了。
- 主回收器
回收的区域是老生代的区域,与副回收器不同的是因为老生代中的对象通常比较大,复制大对象非常耗时,会导致回收执行效率不高,所以采用标记清除法。
主垃圾回收器会直接将标记为垃圾的数据清理掉。然后再单独的做内存整理的工作。
最后就是优化垃圾回收器了
众所周知,js是单线程的。所以执行垃圾回收是会阻塞js的执行的。会造成页面卡顿等问题,使得用户体验不佳。所以V8引擎针对这一系列进行了优化处理:
- 并行回收:主线程执行垃圾回收的同时,引入多个辅助线程来并行处理。例如副回收器。但是还是可能会长时间阻塞运行。
- 增量回收:将回收步骤分解成多个小块进行,减少阻塞的时间。
- 并发回收:主线程在执行 JavaScript 的过程中,辅助线程能够在后台完成执行垃圾回收的操作。
在实际的应用中,这三种回收机制通常是融合在一起用的。
附上原文地址:链接