垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
由于JavaScript是运行在主线程之上的,因此,一旦执行垃圾回收算法,都需要将正在执行的JavaScript脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。我们把这种行为叫做全停顿(Stop-The-World)。
为了解决卡顿问题,向现有的垃圾回收器添加并行、并发和增量等垃圾回收技术。
并行回收
所谓并行回收,是指垃圾回收器在主线程上执行的过程中,还会开启多个协助线程,同时执行同样的回收工作,其工作模式如下图所示:
要实现增量回收的执行,需要满足下边两点:
- 垃圾回收可以被随时暂停和重启,暂停时需要保存当时的扫描结果,等下一波垃圾回收来了之后,才能继续启动。
- 在暂停期间,被标记好的垃圾数据如果被JavaScript代码修改了,那么垃圾回收器需要能够正确地处理。
三色标记法
并发(concurrent)回收
所谓并发回收,是指主线程在执行JavaScript的过程中,辅助线程能够在后台完成执行垃圾回收的操作。并发标记的流程大致如下图所示:
并发回收的难点:
第一,当主线程执行JavaScript时,堆中的内容随时都有可能发生变化,从而使得辅助线程之前做的工作完全无效;
第二,主线程和辅助线程极有可能在同一时间去更改同一个对象,这就需要额外实现读写锁的一些功能了。
并行回收虽然要额外解决以上两个问题,但是仍然是效率高于其他两种方式。
一般实际使用中,并不是单独的存在,通常V8主垃圾回收器会融合这三种机制,来实现垃圾回收。
可以看出,主垃圾回收器采用了这三种策略:
- 首先主垃圾回收器主要使用并发标记,我们可以看到,在主线程执行JavaScript,辅助线程就开始执行标记操作了,所以说标记是在辅助线程中完成的。
- 标记完成之后,再执行并行清理操作。主线程在执行清理操作时,多个辅助线程也在执行清理操作。
- 另外,主垃圾回收器还采用了增量标记的方式,清理的任务会穿插在各种JavaScript任务之间执行。
此文章为6月Day28学习笔记,内容来源于极客时间《图解 Google V8》,日拱一卒,每天进步一点点💪💪
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。