一.内存管理
内存:由可读写单元组成,是一片可操作空间
管理:人为地区操作一片空间的申请、使用和释放
内存管理:开发者主动申请空间、使用空间、释放空间
管理过程:申请-使用-释放
在Js中,内存空间的申请是自动的,声明一个变量或方法等就会自动申请。内存的使用就是访问变量。可以通过把变量赋值为null来释放这片空间。
二.JavaScript中的垃圾回收(GC)算法
GC算法:GC是一种机制,就是垃圾回收器如何完成具体的工作,工作内容就是查找垃圾释放空间、回收空间,算法就是工作时查找和回收所遵循的原则。
常见的GC算法:
1.引用计数
原理:判断当前对象身上的引用计数的数值是否为0,来判断为是垃圾,则进行回收
优点:发现垃圾时立即回收,由于回收及时可最大限度减少程序暂停
缺点:无法回收循环引用的对象,由于时刻维护对象的引用数值导致资源开销大
2.标记清除
原理:遍历所有对象标记其中活动对象,再次遍历你所有对象清除未标记对象以及上次的标记
优点:可回收循环引用的对象,
缺点:会导致内存空间碎片化、容易浪费空间、不会立即回收垃圾对象
3.标记整理
原理:遍历所有对象标记其中活动对象,然后对移动对象位置对内存空间进行整理,再清除未标记对象和上次标记
可看作是标记清除算法的增强版,它可以解决内存空间碎片化的问题
优点:减少空间碎片化
缺点:不会立即回收垃圾对象
4.分代回收
详见后面V8引擎的垃圾回收策略
三.V8引擎的垃圾回收策略
1.认识V8
V8 是一款主流的 Js 执行引擎(应用于Chrome浏览器、node环境)
V8 采用即时编译 速度快
V8 内存设限 (64位系统是1.5G | 32位系统是800M)
2.V8的垃圾分代回收
这里回收的主要是指对象数据 不是原始类型的数据
分代回收的思想:内存分为新生代(对象)存储区、老生代(对象)存储区,针对不同对象采用不同回收算法。
V8常用GC算法:分代回收 空间复制 标记清除 标记整理 标记增量
3.V8如何回收新生代对象
V8把内存空间一分为二
小空间用于存储新生代对象(64位系统是32M | 32位系统是16M)
新生代对象是指存活时间较短的对象(比如一个局部变量)
新生代对象的回收实现:
回收过程采用复制算法 + 标记整理
新生代内存区分为两个等大空间 From 和 To
使用From空间存储新生代对象,To空间空闲
在标记整理过后将活动对象拷贝至 To
From与To交互空间,完成释放
回收细节说明:
拷贝过程中可能出现晋升-将新生代对象移动至老生代对象空间
一轮GC过后还存活的新生代对象需要晋升
或当To空间的使用率达到一定程度(25%)时需要晋升(原因是To空间使用率达到一定程度,当它变成From区域时容易发生不够用的情况)
4.V8如何回收老生代对象
老生代对象存放在右侧老生代区域
64位系统是1.4G | 32位系统是 700M
老生代对象就是指存活时间较长的对象(全局变量等)
老生代对象的回收实现:
主要采用标记清除、标记整理、增量标记算法
首先(主要)使用标记清除算法
然后采用标记整理进行空间优化(当晋升发生且老生代剩余空间又存不下的时候触发标记整理)
最后采用增量标记提高效率(让程序执行 和 标记工作交替执行)
细节对比:
新生代区域回收使用空间换时间
老生代区域空间大数据多 不适合复制算法
注意:垃圾回收进行的时候 会阻塞js执行
四.监控内存的工具(浏览器的任务管理器、F12中的Performance、F12中的内存-堆快照查找分离DOM)
1. 内存问题的体现
页面出现延迟加载或经常性暂停
页面持续出现糟糕的性能
页面性能随时间延长越来越差
2.监控内存的几种方式
内存泄漏: 内存的使用持续升高
内存膨胀: 在多数设备上都存在性能问题
频繁垃圾回收: 通过内存变化图进行分析
3.工具
浏览器任务管理器
F12 Performance Timeline时序图
F12 Memory 堆快照查找 分离DOM
判断是否存在频繁的垃圾回收
五.代码优化的常用建议
慎用全局变量
缓存全局变量(将无法避免使用的全局变量存入局部变量)
通过原型对象添加附加方法
避开闭包陷阱
避免属性访问方法的使用(get)
For循环优化
文档碎片化节点添加
克隆优化节点操作
减少判断层级
减少作用域链查找层级
减少数据读取次数
字面量性能优于构造式
减少循环体中的操作
减少声明及语句数
惰性函数(少用)与性能
采用事件委托
JS代码测试工具:jsBench
本文 完。