Performance 工具
-
为什么使用 Performance
1)GC 的目的是为了实现内存空间的良性循环;
2)良性循环的基石是合理使用;
3)时刻关注才能确定是否合理;
4)Performance 提供多种监控方式,可以时刻监控内存。 -
使用步骤
1)打开浏览器输入目标地址 – Chrome为例;
2)进入开发人员工具面板,选择性能;
3)开启录制功能,访问具体界面;
4)执行用户行为,一段时间后停止录制;
5)分析界面中记录的内存信息 -
内存问题的体现
1)当网络正常时,页面出现延迟加载或经常性暂停 (频繁的垃圾回收);
2)当网络正常时,页面持续性出现糟糕的性能 (内存膨胀);
3)页面的性能随时间延长越来越差(内存泄漏)。 -
界定内存问题的标准
1)内存泄漏:内存使用持续升高;
2)内存膨胀:在多数设备上都存在性能问题;
3)频繁垃圾回收:通过内存变化图进行分析。 -
监控内存的几种方式
1)浏览器任务管理器
在浏览器位置,使用快捷键:Shift + Esc,调出任务管理器。在任务管理器中点击右键,可以调出你想看到的列。
图示分析在任务管理器中,存在两种内存。一种是内存占用空间,他指的是DOM节点所占用的内存。如果他的数值不断增大,则说明界面中在不断的创建新DOM。而另一种则是JavaScript使用的内存,他表示的是JavaScript中的堆,我们所要关注的是小括号中的数据,他表示的是界面中所有可达对象正在使用的内存大小。如果他的数值不断增大,可能是当前界面中正在创建新对象,也可能是当前现有对象在不断的增长。
总结
我们可以通过浏览器任务管理器中的 JavaScript使用的内存的数值变化,来分辨出当前界面的内存是否存在问题。如果JavaScript使用的内存持续增大,则说明存在内存问题。但是浏览器任务管理器只能发现内存问题,而无法定位问题。
那么,接下来我们看一下如何定位到具体的内存问题,以及在哪一个时间节点内发生的?
2)Timeline 时序图记录
首先,我们先来模拟一个不断创建DOM节点以及特别消耗内存的程序。
代码示例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>时间线记录内存变化</title> </head> <body> <button id="btn">Add</button> <script> let arrList = [] function test () { for (let i = 0; i < 100000; i++) { document.body.appendChild(document.createElement('p')) } arrList.push(new Array(1000000).join('x')) } document.getElementById('btn').addEventListener('click', test) </script> </body> </html>
然后,我们在浏览器中运行程序,打开 Performance工具录制时序图,点击按钮,录制结束,可以看到下方图中所示:
在上图中,我们可以看到,在程序执行过程中,JS Heap的趋势图是有增有降的,这也就说明了,在我们程序的运行过程中,是由内存释放的。我们可以通过上方的时间轴来查看每一个时间节点内的内存变化情况,从而确定此时间节点中是否存在内存问题。3)堆快照查找分离 DOM
-
什么是分离 DOM
a. 界面元素存活在 DOM 树上;
b. 垃圾对象时的 DOM 节点;
c. 分离状态的 DOM 节点,只是从 DOM 树上分离,还会被引用(内存泄漏)。 -
如何查找分离 DOM
首先,我们先来模拟一个拥有分离 DOM 的程序。
代码示例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>堆快照监控内存</title> </head> <body> <button id="btn">Add</button> <script> // 新建 DOM,但是不把它放在界面中,而是使用一个变量进行引用 let temEle function fn () { let ul = document.createElement('ul') for (let i = 0; i < 10; i++) { let li = document.createElement('li') ul.appendChild(li) } temEle = ul } document.getElementById('btn').addEventListener('click', fn) </script> </body> </html>
然后,使用浏览器打开,并打开开发工具,找到堆快照,堆快照的位置如图:
下面,我们来做两个行为的测试。首先,我们使用浏览器打开程序后,什么都不做,先来拍快照,此时,我们会看到如下图所示的内容:
此时我们搜索 “deta”(Detached 缩写),发现是没有结果的。
接下来,我们点击 Add 按钮,执行DOM的新建。执行刚才的拍快照操作,并搜索“deta”,会出现如下图所示的结果:
上面查询出来的DOM节点,并没有在界面中展示,也就是说,它们其实就是分离DOM,会造成内存浪费。 -
总结
通过堆快照,可以发现具体的分离DOM,从而采用对应的方法去处理,释放内存,节省内存空间。
4)判断是否存在频繁的垃圾回收
-
为什么确定频繁垃圾回收
a. GC 工作时应用程序是停止的;
b. 频繁且过长的 GC 会导致应用假死;
c. 用户使用中感知应用卡顿。 -
确定频繁的垃圾回收
a. Timeline 中频繁的上升下降;
b. 任务管理器中数据频繁的增加减小。
-