chrome-v8的垃圾回收机制

1,015 阅读5分钟

chrome-v8的垃圾回收机制

前言

今天记录一下chrome-v8的垃圾回收相关的知识,有兴趣的小伙伴可以一起来看看

v8是什么?

v8是chrome浏览器的JavaScript执行引擎,用来执行JavaScript,性能非常优越;

v8与node有什么关系?

node中JavaScript执行引擎就是使用的v8,而node是主要用JavaScript来编程的服务端语言,可想而知,v8对于node的重要性,相当于node的心脏;

同时node还将享受v8升级优化带来的更好的性能,更新的语言特性;但也将受到和v8一样的相关限制;

v8在内存使用上有什么特点?

1. node通过JavaScript使用内存时,只能使用部分内存;

*默认(64位系统约为1.4G,32位系统约为0.7G)*

2. 所有JavaScript对象都是通过堆来进行分配的;

3. v8可以通过特定自定义配置,增大内存使用申请;

可以通过

node --max-old-space-size=1700 test.js // 单位为MB

node --max-new-space-size=1024 test.js // 单位为MB

来申请更多的内存空间;

为什么要限制v8对内存的使用?

这里有两个原因:

1、表层原因为V8最初为浏览器而设计,不太可能遇到用大量内存的场景;

2、深层原因是V8的垃圾回收机制的限制;

以1.5G的垃圾回收堆为例:

V8做一次小的垃圾回收需要50ms以上;

V8做一次非增量式垃圾回收甚至要1s以上;

然后当垃圾回收时,将引起JavaScript线程的执行中断,导致运用的性能和响应能力急剧下降;这样的情况在前后端都是不能接接受的;所以当时选择直接限制内存也不失为一个好的选择;

V8的垃圾回收机制是怎么样的呢?

V8的垃圾回收策略主要基于分代垃圾回收机制

简单来说,V8将内存分为新生代和老生代两种。

新生代中的对象为存活时间较短的对象,老生代的对象为存活时间较长的或长驻内存的对象。

V8堆的整体大小就是新生代内存加上老生代内存之和。

新生代内存与老生代内存的特点

新生代内存较小,64位系统中最大为32MB;32位系统中最大为16MB;存储的对象也是短时间存储;

老生代的内存较大,存储的对象时间较长;

之所以这样分配,是应为实际运用中,短时间存储的对象较少,长时间存储的对象就非常多了;

几种在V8垃圾回收机制中使用的算法

Scavenge算法

新生代对象主要通过Scavenge算法进行垃圾回收

Scavenge的具体实现主要采用了Cheney算法,这是一种采用复制的方式实现的垃圾回收机制。

1、首先将堆内存分为两份,每一部分空间成为semiSpace;

2、在这两个空间中,只有一个处于使用状态,另外一个处于闲置状态;分别叫做From空间与To空间;

3、当我们分配对象时,先是在From空间进行分配,当开始进行垃圾回收时,会检查From空间中的存活对象,这些存活对象将被复制到To空间中,而非存活对象占用的空间将被释放;

4、复制完成后,From空间将与To空间进行角色对换,To空间变为使用中状态,From变为闲置状态;此时内存写入将写到调换后的To空间中;

Scavenge的缺点是只能使用堆内存的一半,是典型的牺牲空间换取时间的算法,无法大规模的运用到所有的垃圾回收中;

1.png

Mark-Sweep & Mark-Compact算法

Mark-Sweep是标记清除的意思,它分为标记与清除两个阶段;

1、标记阶段遍历堆中的所有对象,并标记活着的对象

2、清除阶段,清除没有被标记的对象

可以看出,Scavenge中只复制活着的对象,而Mark-Sweep只清理死亡的对象;

活对象在新生代中只占小部分,死对象在老生代中只占较小部分,这是两种回收方式能高效处理的原因

Mark-sweep最大的问题是在进行一次标记清除回收后,内存空间将出现不连续的状态,这种内存碎片会对后续内存分配造成问题,因为很可能出现需要分配一个大对象的情况,这时将无法完成存储;

Mark-Compact是被提出来解决Mark-Sweep的内存碎片化问题

Mark-Compact是标记整理的意思,是在Mark-Sweep的基础上演变而来的;

Mark-Compact将在对象标记死亡后,在整理过程中,将活着的对象往一端移动,移动完成后,直接清理掉边界内存;

2.png

2.png

Incremental Marking算法

为了避免JavaScript运用逻辑与垃圾回收器看到的不一致的情况,垃圾回收的3中基本算法都需要暂停运用逻辑,待执行玩垃圾回收后再恢复执行运用逻辑,这种行为被称为全停顿(stop-the-world);

为降低全堆垃圾回收带来的停顿时间,V8将原本需要一口气停顿完成的动作改为增量标记,拆分为许多小的步骤,每做完一个小步骤,就短暂的让运用逻辑执行一会儿,再进行垃圾回收,如此交替完成;

V8引入增量标记后,垃圾回收的最大停顿时间可以减少到原本的1/6左右;

总结

以上,大概了解了V8垃圾回收的一些知识,如果还需要更加详细的了解相关的处理方法和基本原理,需要更加精细的资料,有兴趣的小伙伴可以去找更加细微的书籍和博客了解