一、内存管理
1) 内存:由可读写单元组成,表示一片可操作空间
2) 管理:人为的去操作一片空间的申请,使用和释放
3) 内存管理:开发者主动申请空间,使用空间,释放空间
4) 管理流程:申请————使用————释放
二、垃圾回收与常见 GC 算法
1、JavaScript中的垃圾回收
1) JavaScript 中的内存管理是自动的
2) 对象不再被引用时是垃圾
3) 对象不能从根上访问到时是垃圾
JavaScript的可达对象:我们可以访问到的对象就是可达对象(引用、作用域链)
————可达的标准就是从根上触发是否能够被找到
JavaScript中的根可以理解为是全局变量对象
2、GC的定义与作用
1) GC就是垃圾回收机制的简写
2) GC可以找到内存中的垃圾、并释放和回收空间
程序中不再需要使用的对象、程序中不能再访问到的对象
3) 算法就是工作时查找和回收所遵循的规则
(引用计数、标记清除、标记整理、分代回收)
3、 引用计数算法:
核心思想:设置引用数,判断当前引用数是否为0
引用计数器
引用关系改变时修改引用数字
引用数字为0时立即回收
优点 发现垃圾时立即回收,最大限度减少程序暂停
缺点 无法回收循环引用的对象,资源消耗比较大
4、 标记清除算法:
核心思想:分标记和清除两个阶段完成
遍历所有对象找到并标记活动对象
遍历所有对象清除没有标记的对象
回收相应的空间
优点 可以找到一些局部作用域的垃圾,可以解决引用计数算法中无法回收循环引用的问题
缺点 不会立即回收垃圾对象,地址不连续、空间碎片化、浪费空间
5、 标记整理算法:
标记整理可以看作是标记清除的增强
标记阶段的操作和标记清除一致
清除阶段会先执行整理,移动对象位置
优点 减少碎片化空间
缺点 不会立即回收垃
三、V8 引擎的垃圾回收
1) V8是一款主流的JavaScript执行引擎
2) V8采用即时编译
3) V8内存设限(64位1.5G,32位800MB)
1、V8垃圾回收策略
1) 采用分代回收的思想
2) 内存分为新生代、老生代
2、V8中常见的GC算法
* 分代回收
* 空间复制
* 标记清除
* 标记整理
* 标记增量
3、V8如何回收新生代对象
1) V8内存空间一分为二
2) 小空间用于存储新生代对象(32M | 16M)
3) 新生代制的是存活时间较短的对象
新生代对象回收实现:
1) 回收过程采用复制算法+标记整理
2) 新生代内存区分为二个等大空间,使用空间为From,空闲空间为To
3) 活动对象存储于From空间
4) 标记整理后将活动对象拷贝至To
5) 清除From空间完成释放,并交换From和To的空间
回收细节说明
1) 拷贝过程中可能出现晋升
2) 晋升就是将新生代对象移动至老生代
3) 一轮GC还存活的新生代需要晋升
4) To空间的使用率超过25%时会将所有To空间中的对象晋升
4、V8如何回收老生代对象
1) 老生代对象存放在老生代区域
2) 大空间用于存储老生代对象(1.4G | 700M)
3) 老生代对象就是指存活时间较长的对象(全局变量,闭包)
老生代对象回收实现:
1) 主要采用标记清除、标记整理、增量标记算法
2) 首先使用标记清除完成垃圾空间的回收
3) 采用标记整理进行空间优化(当新生代晋升老生代时,老生代空间的碎片不足以存放时)
4) 采用增量标记进行效率优化
5、增量标记优化垃圾回收
程序执行时交替执行垃圾回收处理,分层遍历对象进行标记,最后完成清除。
四、Performance 工具
1、GC的目的是为了实现内存空间的良心循环
2、良心循环的基石是合理使用
3、时刻关注才能确定是否合理
4、Performance提供多种监控方式
5、使用步骤:
1) 打开浏览器输入目标网址
2) 进入开发人员工具,选择性能
3) 开启录制功能,访问具体界面
4) 执行用户行为,一段时间后停止录制
5) 分析界面中记录的内存信息
五、如何判断内存的问题
1、内存问题的体现
1) 页面出现延迟加载或者经常性暂停:频繁的垃圾回收,程序代码产生的垃圾过多
2) 页面持续性出现糟糕性能表现:内存膨胀,当前界面为了达到一定的使用速度,会去申请一定的使用空间,这个空间的大小远超过我们能够提供的空间大小
3) 页面的性能随时间延长越来越差:内存泄漏,由于某种原因无法被回收的内存。
2、界定内存问题的标准
1) 内存泄漏:内存持续升高
2) 内存膨胀:在多数设备上都存在性能问题
3) 频繁垃圾回收:通过内存变化图进行分析
3、监控内存的几种方式
1) 浏览器任务管理器
打开浏览器,通过shift+esc打开任务管理器,右击打开JavaScript使用内存
如果小括号里的内存一直增加没有进行消耗,就存在内存泄漏问题
2) Timeline时序图记录
打开浏览器,F12,找到Performance,录制屏幕,监控内存走势
3) 堆快照查找分离DOM
什么是分离DOM:从当前的DOM树上脱离了,在JS代码中被引用。
打开浏览器,F12,找到Memory,选择Profiles=>Heap snapshot=>takeSnapshot=>筛选'deta'就可以得到所有分离DOM
4) 判断是否存在频繁的垃圾回收
当GC工作状态,应用会假死,如果GC频繁且过长,用户会感受到比较差的性能体验
Timeline中频繁的上升下降