内存管理
- js中的内存管理是自动的,对象不再被引用或者不能从根上访问到时视为垃圾。
- 可达对象:从根(js中的根可以理解为全局变量对象)出发可以被找到的对象。
// 内存管理分为申请、使用、释放内存空间
// 申请
let obj = {}
// 使用
obj.name = 'lily'
// 释放
obj = null
垃圾回收和常见的GC算法
- GC(垃圾回收机制):可以找到内存中的垃圾(程序中不再需要使用或不能再访问到的对象)、并释放和回收空间。
- 常见的GC算法:引用计数、标记清除、标记整理、分代回收
引用计数
- 核心思想: 设置引用数,判断当前引用数是否为0。当引用关系改变时,引用计数器会修改引用数字,引用数字为0时立即回收。
- 优点:可以立即回收垃圾对象。
- 缺点:无法回收循环引用的对象。时间开销大。
标记清除
- 核心思想: 遍历所有对象并标记活动对象,再遍历所有对象清除没有标记的对象
- 缺点:要清除的几个对象如果内存空间地址不连续,清除后会导致空间碎片化。不能立即回收垃圾对象。
标记整理
- 核心思想: 标记清除的增强版,标记之后,在清除时会先执行整理,移动活动对象位置使其在地址上产生连续
V8引擎的垃圾回收
V8: 主流的 js 执行引擎,采用即时编译,内存设限(64位1.5G,32位800M)
- 基础类型数据都是由语言本身来控制的,所以回收策略是针对于活在堆内存中的对象数据。
- V8 中常用的 GC 算法:分代回收、空间复制、标记清除、标记整理、标记增量
分代回收
- V8将内存空间一分为二,分为新生代和老生代存储区
- 小空间(64位32M|32位16M)用于存储新生代对象( 指存活时间较短的对象,比如局部作用域中的对象 )
- 大空间(64位1.4G|32位700M)用于存储老生代对象( 指存活时间较长的对象,比如全局作用域中或者闭包中的对象 )
新生代回收
空间复制 + 标记整理:空间换时间
- 新生代内存区也分为两个等大的空间:From(使用空间), To(空闲空间)
- 活动对象都存储在 From 空间,触发GC机制时,会进行标记整理
- 在标记整理的过程中可能会出现晋升,就是将新生代对象移动到老生代:
- 一轮 GC 还存活的新生代需要晋升
- To 空间的使用率超过 25%
- 标记整理之后将活动对象拷贝到 To 空间
- 交换 From 和 To 空间,完成 From 空间的释放
老生代回收
标记清除 + 标记整理 + 标记增量
- 使用标记清除完成垃圾空间的回收
- 当发生晋升,发现老生代空间不足以存储移过来的新生代对象时,采用标记整理进行空间优化
- 采用标记增量进行效率优化:垃圾回收会阻塞当前程序的执行,标记增量就是将标记过程分段执行,使得垃圾回收可以和当前程序交替进行,用户体验更好
学习自拉钩教育前端视频