使用DevTools进行网页内存分析
开启DevTools
DevTools为Chrome浏览器自带工具,下载并启动Chrome浏览器后,在需要进行内存分析的页面按下F12或者Shift+Ctrl+I启动DevTools开发者工具。
获取js堆内存快照
在内存界面下选择堆快照,点击获取快照即可对当前页面进行一次内存快照。


堆快照分析
摘要(Summary)
摘要展示当前内存快照的概览。其中:
- 构造函数(Constructor):表示对象的构造器
- 距离(Distance):与GCroot的引用链距离。当出现同一类对象距离不同的情况,要注意代码逻辑可能出现问题。
- 对象计数(Object Count):跟在构造器后方的灰色数字,表示当前构造器所构造的对象总数。
- 浅层大小(Shallow Size):对象自身占用的内存大小。
- 保留大小(Retained Size):当一个对象被释放后,系统虚拟机可以释放的总内存。

在摘要界面的右侧有一个选择栏,用户可以选择查看特定的对象,例如下图中选择“在快照2和快照3之间分配的对象”,这样生成的摘要可以用于定位内存问题发生的位置。

比较(Comparison)
在比较(Comparison)中可以将当前快照与另一个快照比较,跟踪对象属性和内存占用的变化。其中:
- 构造函数:对象的构造器。
- 新对象数(New):该对象构造器下有多少新的对象被创建。
- 已销毁(Deleted):该对象构造器下有多少新对象被销毁。
- 增量(Delta):新对象与被删除对象的差值。
- 分配大小(Alloc Size):两份快照间分配的内存大小。
- 已释放大小(Freed Size):两份快照间释放的内存大小。
- 大小增量(Size Delta):分配大小和已释放大小的差值。
可以根据比较界面不同快照间的差异分析内存问题。

控制(Containment)
控制(Containment)提供了一个自上而下的树形界面,该界面允许浏览和探索堆内存中的内容。我们可以用它来分析任意变量的引用情况。

统计信息(Statistics)
统计信息(Statistics)用一个饼图展示各个类型对象的内存占用比例。

内存泄漏分析流程
-
打开一个可能存在内存泄漏问题的页面并启用DevTools。下图展示的页面来自GitHub上的memory-leak-simulation项目,该网页通过设置全局数组并不断向其推入'memory leak'字符串来模拟内存泄漏场景。

-
在性能界面录制可能导致内存泄漏的用户操作,以识别引起内存泄漏的用户操作或组件。下图显示,网页已加载完毕,但内存仍在持续上升,表明可能存在内存泄漏问题。对于包含大量动态组件和频繁DOM操作的网页,内存曲线可能呈起伏状态。持续观察内存起伏的最低值变化,若最低值逐渐上升,怀疑网页存在内存泄漏问题。

-
我们对这个网页进行第一次堆快照,发现Array占用了28M内存,基于该对象的内存占用显著高于正常值(通常在几MB范围内),可以判断该对象可能存在内存泄漏问题。

-
对网页进行可能会造成内存泄漏的操作,操作完成后进行第二次堆快照,然后选择两个快照间分配的对象,观察到Array构造器新产生约16MB内存占用。

-
查看比较(comparison),选择快照3并使用快照2作为比较对象,观察到Array构造器新产生了4030个对象,占用了16.1MB空间,但只释放了184B空间,根据此结果,确定内存泄漏发生在Array中。

-
录制1-2分钟的堆快照来获得包含时间轴的摘要视图,这与性能界面中的视图类似。使用此视图可以分析是哪个动作造成了内存占用的变化。录制快照时选择“时间轴上的分配情况”选项,点击录制。完成想要测试的动作后,停止录制即可生成内存堆时间轴视图。

-
在结果的时间轴上,使用左键滑动选择想要查看的区域,即可查看选定时间段内的内存分配情况。从下图中框选部分可以看到,在选定时间内,Array构造器产生了两千个新对象。利用该功能,可以明确不同操作对内存的影响。
