V8 是一款当下较为主流 JavaScript 执行引擎,采用即时编译,处理速度很快。V8 的内存是设限的,比如 64 位操作系统的上限是 1.4T,下限是 700M,32 位操作系统的上下限分别为 64M 和 32M。

V8 采用分代回收的垃圾回收策略,将内存分为新生代和旧生代两种,并对不同的对象采用不同的对应算法。

#yyds干货盘点#简述chromeV8引擎垃圾回收_v8

#yyds干货盘点#简述chromeV8引擎垃圾回收_垃圾回收_02

上图是 V8 的内存分配示意图,可以清除看到 V8 内存空间分为两部分。左边的 from 和 to 是新生代,占用的空间比较小(32M|16M),这里的新生代指的是存活时间短的存储区。右边红色的部分则是存活时间较长的老生代存储区。

​V8 常用的 GC 算法有以下 5 种:

  • 分代回收
  • 空间复制
  • 标记清除
  • 标记整理
  • 标记增量

这其中新生代采用复制算法和标记整理进行垃圾回收,老生代使用标记清除、标记整理和增量标记进行垃圾回收。


V8 新生代对象回收实现

#yyds干货盘点#简述chromeV8引擎垃圾回收_位操作_03

上图为 V8 新生代对象回收实现图,采用复制算法和标记整理结合的方式进行垃圾回收。新生代内存区的两个等大空间,From 代表使用空间用于存储活动对象,To 代表空闲空间。V8 的新生代对象回收是通过标记整理将对象完成整理后拷贝到 To,然后将 To 和 From 进行空间交换,并释放整理后的无用对象所占空间。需要注意的是,在将整理对象拷贝到 To 时可能会出现晋升。晋升指的是将新生代对象移动至老生代存储区。晋升通常有两个条件,其一是在进行一轮 GC 后还活着的新生代对象可以晋升,其二是 To 空间的使用率超过 25%。

V8 老生代对象回收实现

V8 老生代的回收过程采用标记清除、标记整理和标记增量结合的方式。一般在进行垃圾回收时会通过标记清除完成垃圾空间的回收,但是当新生代移动到老生代,而老生代内存不够时,则会通过标记整理进行空间优化,并使用增量标记进行效率优化。

#yyds干货盘点#简述chromeV8引擎垃圾回收_v8_04

​标记增量其实是通过对标记操作进行标记的方法,让时间安排变得合理。这句话可能有些绕,简单说就是在垃圾回收时,让标记系统在标记时分出不同的时间段,分别进行标记和执行,让二者的操作间隔开,从而优化时间安排,这会让页面在体感上更为顺畅。