引用计数算法
核心思想:设置引用计数,判断当前引用数是否为 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 中回收新生代对象(存活时间较短的对象)
- 小空间用于存储新生代对象(32M | 16M)
- 主要用到复制算法 + 标记整理
- 小空间分为 from 和 to 两块空间
- 活动对象存储于 from 空间
- 标记整理后将活动对象拷贝至 To
- from 与 to 交换空间后,完成 from 空间释放
晋升
晋升就是将新生代对象移动至老生代。1.一轮 GC 还存活的新生代需要晋升;2.To 空间的使用率超过 25%,新的活动对象不够用也会晋升。
v8 中回收老生代对象(存活时间较长的对象)
- 老生代内存大小:64 位操作系统中 1.4G 和 32 位操作系统 700M
- 主要算法:标记清除、标记整理、标记增量
- 首先使用标记清除完成垃圾空间的回收
- 采用标记整理进行空间优化(晋升)
- 标记增量算法提升效率
- 标记增量:把程序的执行分为很多小块,标记和代码执行交替执行。
- 当数据达到 1.5G 时才采用标记增量。
老生代与新生代对比
- 新生代区域垃圾回收使用空间换时间(复制算法)
- 老生代数据较大不适用复制算法