内存泄漏的症状
-
网页的性能效果会随着时间的推移逐渐变差:这可能是<u>内存泄漏</u>的症状。内存泄漏是使用过后不再使用的内存未被释放。
-
网页的效果始终不佳:这可能是<u>内存膨胀</u>的症状。内存膨胀是指页面使用的内存过大。
-
网页的效果延迟或频繁暂停: <u>频繁的垃圾回收</u>症状。浏览器决定何时回收内存。在回收内存期间,所有脚本执行都将暂停。
使用谷歌开发者工具分析内存泄漏
1. 查看整体内存占用
按Shift + Esc打开谷歌的<u>任务管理器</u>。或点击右上角菜单--更多工具---任务管理器。关注内存占用空间、javascript使用的内存。
image.png操作步骤
- 内存占用空间: 本机内存,如果这个值在增加,说明正在创建DOM节点。
- Javascript使用的内存:JS堆,跳动的数字表示网页上<u>活动对象</u>使用的内存,如果这个数字在增加,说明正在创建新对象或现有对象正在增长
什么是活动对象 ?
有引用的对象为可获得的对象,也称为活动对象。没有引用的对象是不可获得的对象,会被垃圾机制回收。
如:
var arr = new Array();
new Array()创建了一个新的数组对象,arr是它的引用,如果我们这时把arr = null
那数组对象就无法再被我们调用了,这时就会被当成垃圾回收
常见的几种情况及原因
(1)内存占用空间一直在增长,JavaScipt使用的内存没增长:浏览器还没有进行垃圾回收
(2)内存占用空间一直在增长,JavaScipt使用的内存增长很慢:JS变量引用了DOM,影响了其他DOM节点
2. Performance面板
2.png- 启用Memory(内存)复选框
- 点击垃圾回收 -> 点击开始录制 -> 点击垃圾回收 -> 点击结束录制
会得到图如下
3.png
(1)Heap堆:曲线表示JS堆,在后面的Memory面板会重点说明
(2)Call stack 调用栈:横向表示调用时间,如果调用时间过长,就要进行优化。垂直方向无意义,主要表示函数嵌套较深。
(3)Counter 计数器:显示内存的使用情况,分别显示
- JS Heap:JS堆
- Documents:文档
- Nodes: DOM 节点
- Listeners:侦听器
- GPU Memory:GPU内存
主要关注JS Heap、Nodes、Listeners。如果这三个中有一个在持续上涨,并且没有下降的趋势,就有可能是内存泄漏
3. Memory 面板
4.png操作步骤
- 选择快照堆类型:一般选Heap snapshot(JS堆快照)和Allocation instrumentation on timeline(JS堆分配时间线)
- 点击垃圾回收 -> 开始录制
- 录制完成后得到堆快照
Heap snapshot(JS堆快照):发现DOM泄漏
Allocation instrumentation on timeline(JS堆分配时间线): 显示了对象什么时候被创建,什么时候存在内存泄漏(蓝色线表示未回收、灰色线表示已回收)
视图类型
-
Summary: 总览视图,
按构造函数分组。用于捕捉对象及其使用的内存。对于定位DOM内存泄露特别有用。 -
Comparison:对比视图
用于对比不同操作之后的堆快照,查看内存的释放及引用计数,来分析内存是否泄露及其原因。 -
Containment:内容视图
查看堆内容。更适合查看对象结构,有助于分析对象的引用情况。适用于分析闭包以及深入分析对象。 -
Statistics:统计视图
总览堆的统计信息。
JS快照堆
以以下代码为例说明
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<button id="createBtn">增加节点</button>
<script>
function create() {
var ul = document.createElement('ul');
for (var i = 0; i < 10; i++) {
var li = document.createElement('li');
ul.appendChild(li);
}
detachedNodes = ul;
}
document.getElementById('createBtn').addEventListener('click', create);
</script>
</body>
</html>
- 多次录制对比堆快照
1、无任何操作,拍第一个堆快照
2、执行你觉得可能造成内存泄露的操作,再执行相反操作
3、拍第二个堆快照,切换到视图类型为Comparison(对比视图),并且指定与第一个堆快照对比
<u>记得每次录制之前要先点击垃圾回收</u>
如:
点击垃圾回收 => 打开页面后立即录制一次堆快照 => 点击按钮 => 点击垃圾回收 => 录制一次堆快照 => 选中一个堆快照切换视图类型为Comparison(对比视图)并与另一个快照进行比较
6.png
JS堆分配时间线
使用上面的例子,操作如下图
高度代表这个对象的大小
颜色代表这个对象的内存释放情况:蓝色线代表在录制结束前未被回收的,灰色线代表已经被回收了。
我们可以重复执行某个动作,如果有不少蓝色柱被保留,那就发生了内存泄漏
选中某段时间内的时间线,可以具体分析在这个时间点变化的对象
8.png常见的内存泄漏
1. 常见JS内存泄漏
- 全局变量引起的内存泄漏
- 闭包引起的泄漏
- DOM删除时没有解绑事件
- 定时器没有清除
网友评论