文章目录
- 定义
- 引起内存泄漏的操作:
- Chrome 控制台查看内存情况
- 无痕模式
- Performance
- Memotry
- 1. 先用 Allocation instrumentation on timeline 确认问题
- 2. 再用 Head snapshot 定位代码
- 闭包函数使用不当
js内存泄露如何检测?场景有哪些?如何定位到具体代码?
定义
程序中已动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题,如浏览器变慢,奔溃,延迟大
引起内存泄漏的操作:
- 闭包函数使用不当
- 未使用的 var 声明的全局变量
- 循环引用
- 控制台日志(
console.log
)
Chrome 控制台查看内存情况
无痕模式
打开Chrome的无痕模式,这样做的目的是为了屏蔽掉Chrome插件对我们之后测试内存占用情况的影响
Performance
在页面从零到加载完成这个过程中
JS Heap
(js堆内存)、documents
(文档)、Nodes
(DOM节点)、Listeners
(监听器)、GPU
memory(GPU内存)的最低值、最高值以及随时间的走势曲线
Memotry
作用:用于记录页面堆内存的具体情况以及js堆内存随加载时间线动态的分配情况
1. 先用 Allocation instrumentation on timeline 确认问题
在开始记录后,我们可以看到图中右上角有起伏的蓝色与灰色的柱形图,其中
蓝色
表示当前时间线下占用着的内存;灰色
表示之前占用的内存空间已被清除释放
2. 再用 Head snapshot 定位代码
闭包函数使用不当
// 其中,arr被赋值给 res,arr 被标记为活动变量并一直占用着相应的内存,假如 res 后续用不到,这内存就一直占用
<button onclick="btnClick()">点击</button>
<script>
function test() {
let arr = new Array(1000000);// 一个很大的数组对象
function fn() {
let c = [1, 2, 3]
}
fn()
return arr
}
let res = []
function btnClick() {
res.push(test())
}
</script>
- 先使用 performacne 的曲线图
在每次录制开始时手动触发一次
垃圾回收机制
,这是为了确认一个初始的堆内存基准线
,便于后面的对比,然后我们点击了几次按钮,即往全局数组变量res中添加了几个比较大的数组对象,最后再触发一次垃圾回收
,发现录制结果的JS Heap
曲线刚开始成阶梯式上升的,最后的曲线的高度比基准线要高
,说明可能是存在内存泄漏的问题
- 用 Allocation instrumentation on timeline 手机动态内存分配情况
动态内存分配情况图上都会出现一个蓝色的柱形,并且在我们触发垃圾回收后,蓝色柱形都
没变成灰色柱形
,即之前分配的内存并未被清除,确认内存泄漏的问题是存在的
- 用 Head snapshot 定位
所以选择Object allocated between Snapshot1 and Snapshot2即展示第一条快照和第二条快照存在
差异的内存对象分配
情况,Array的百分比
很高,初步可以判断是该变量存在问题
避免策略:
- 减少不必要的全局变量
- 避免"死循环"
- 避免创建过多的对象
- 减少层级过多的引用