前端V8引擎分析 垃圾回收策略

244 阅读3分钟

v8引擎

  • V8是一款主流的JavaScript执行引擎
  • V8采用即使编译(将源码直接翻译为机器可执行的机器码)
  • V8内存设上限(64位 不超过1.5g 32位不超过800M)

V8垃圾回收策略

  • 采用分代回收思想
  • 内存分为新生代 老生代
  • 对不同对象采用不同算法

image.png

V8中常用GC算法

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

V8如何回收新生代

  • V8内存空间一分为二
  • 小空间用于存储新生代对象(32M|16M)
  • 新生代指的是存活时间较短的对象(如函数的局部作用域在函数执行完成后就被释放)

V8内存示意图

image.png

新生代对象回收实现

  • 回收过程采用复制算法 + 标记整理
  • 新生代内存区分为两个等大小的空间
  • 使用空间为From,空闲空间为To
  • 活动对象存储于From空间
  • 标记整理后将活动对象拷贝至To
  • From 与 To交换空间完成释放

新生代内存区域被分成两个等大小的区域 From|To,当前使用的是From区域 所有的对象声明都会放在From区域内,当触发Gc机制时 会将当前From内所有的活动对象全都找到,并复制到To内容区域内,拷贝完成后将From和To的空间区域进行交换,From变成To To变成From 完成释放

image.png

回收细节说明

  • 拷贝过程中可能出现晋升
  • 晋升就是将新生代对象移动至老生代
  • 一轮GC还存货的新生代需要晋升
  • 拷贝过程中To空间的使用率超过25%会将当前活动对象拷贝至老生代

为何To的使用限制是25% 因为 如果占用空间超过限制值之后 From To置换完成后 留给用户存储空间不够用

V8如何回收老生代

老年代对象说明

  • 老年代对象存放在右侧老生代区域
  • 老年代内容大小 64位操作系统1.4G,32位操作系统700M
  • 老生代对象就是指存货时间较长的对象

老年代对象回收实现

  • 主要采用标记清除、标记整理、增量标记算法
  • 首先使用标记清除完成垃圾空间的回收
  • 采用标记整理进行空间优化 (合适采用标记整理,当新生代出现晋升时 新生代内容复制存储到老生代,但是当前老生代内存区域没有完整连续的内存空间进行存储,就会进行标记整理,优化碎片空间)
  • 采用增量标记进行效率优化

新老细节对比

  • 新生代区域垃圾回收使用空间换时间(等分成两个区域模块,复制交换空间)
  • 老生代区域垃圾回收不适合复制算法(老生代存储区域较大,存储内容较多 采用复制算法消耗太大)

增量标记算法优化老生代垃圾回收

将整段的垃圾回收差分成多段交替执行

image.png

遍历对象进行标记 标记分为 直接可达和间接可达。

v8总结

  • V8是一款主流的JavaScript执行引擎
  • V8内存设置上限: v8内存大小 是根据该内存满足应用所需和用户使用体验感知而来
  • V8采用基于分代回收思想实现垃圾回收
  • V8内存分为新生代和老生代
  • V8垃圾回收常见的GC算法