V8 GC的算法整理

360 阅读2分钟

引用计数算法

核心思想:设置引用计数,判断当前引用数是否为 0,引用关系改变时修改引用数字,引用数字为 0 时 GC 立即回收。

const user1 = { age: 11 }
const user2 = { age: 22 }
const user3 = { age: 33 }
const nameList = [user1.age, user.age]
  • 优点: 即时回收垃圾对象,减少程序卡顿时间
  • 缺点:1. 无法回收循环引用的对象 2. 资源消耗大

循环引用

function fn() {
  const obj1 = {}
  const obj2 = {}

  obj1.name = obj2
  obj2.name = obj1
  return ''
}

标记清除算法

核心思想: 分为标记和清除两个阶段完成,遍历所有对象找标记活动对象,遍历所有对象清除没有标记对象,回收相应空间。

  • 优点:1. 可以回收循环引用对象

  • 缺点:1.空间碎片化 2.不会即时回收垃圾对象

标记整理算法

核心思想:标记算法的增强,标记阶段的操作和标记清除一致,清除整理阶段会先执行整理,移动对象位置,使地址是连续的。

  • 优点:减少空间碎片化
  • 缺点:不会即时回收垃圾对象

V8 垃圾回收策略

  • v8 采用即时编译的,内存设限
  • V8 采用分代回收的思想,内存分为新生代和老生代,不同区分别采用不同的 GC 算法
  • GC 算法(分代回收、空间复制、标记清除、标记整理、标记整理)

v8_gc.png

v8 中回收新生代对象(存活时间较短的对象)

  • 小空间用于存储新生代对象(32M | 16M)
  • 主要用到复制算法 + 标记整理
  • 小空间分为 from 和 to 两块空间
  • 活动对象存储于 from 空间
  • 标记整理后将活动对象拷贝至 To
  • from 与 to 交换空间后,完成 from 空间释放
晋升

晋升就是将新生代对象移动至老生代。1.一轮 GC 还存活的新生代需要晋升;2.To 空间的使用率超过 25%,新的活动对象不够用也会晋升。

v8 中回收老生代对象(存活时间较长的对象)

  • 老生代内存大小:64 位操作系统中 1.4G 和 32 位操作系统 700M
  • 主要算法:标记清除、标记整理、标记增量
  • 首先使用标记清除完成垃圾空间的回收
  • 采用标记整理进行空间优化(晋升)
  • 标记增量算法提升效率
  • 标记增量:把程序的执行分为很多小块,标记和代码执行交替执行。
  • 当数据达到 1.5G 时才采用标记增量。

老生代与新生代对比

  • 新生代区域垃圾回收使用空间换时间(复制算法)
  • 老生代数据较大不适用复制算法