使用DevTools进行网页内存分析
==================

#### 开启DevTools

DevTools为Chrome浏览器自带工具，[下载](https://www.google.com.hk/intl/en_uk/chrome/)并启动Chrome浏览器后，在需要进行内存分析的页面按下F12或者Shift+Ctrl+I启动DevTools开发者工具。

#### 获取js堆内存快照

在内存界面下选择堆快照，点击获取快照即可对当前页面进行一次内存快照。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/77/v3/FUMdahpoQZ-srKU9f33iuQ/zh-cn_image_0000002594669686.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=33A181363C1ABD7E7DA26EDBE0D7A9338B47BF0B818D84225EE36C5012F81FDF)

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ea/v3/PmtHbAztQ--DE0Lp25Xk_g/zh-cn_image_0000002594829614.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=96287BC9B4CFDD12C598BAFD5B6D947FC2CD4442A7099EFE010A26EB5DAB8128)

#### 堆快照分析

#### \[h2\]摘要(Summary)

摘要展示当前内存快照的概览。其中：

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

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e9/v3/Wz58EF0rRbmwX9zchiDFNg/zh-cn_image_0000002625189061.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=4D3FBF27802AEEF528B5BD93BDCD5E0B118933594C0F255E655BB7FC087773F3)

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

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/a3/v3/zxDs3RrWSPOe6pODOwFJcg/zh-cn_image_0000002625109205.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=9AD3BF19F249FFA31050BDF1B3A4E8145AB30CAFF9BBAE4E00B7BFA3EF42BBE7)

#### \[h2\]比较(Comparison)

在比较(Comparison)中可以将当前快照与另一个快照比较，跟踪对象属性和内存占用的变化。其中：

*   构造函数：对象的构造器。
*   新对象数(New)：该对象构造器下有多少新的对象被创建。
*   已销毁(Deleted)：该对象构造器下有多少新对象被销毁。
*   增量(Delta)：新对象与被删除对象的差值。
*   分配大小(Alloc Size)：两份快照间分配的内存大小。
*   已释放大小(Freed Size)：两份快照间释放的内存大小。
*   大小增量(Size Delta)：分配大小和已释放大小的差值。

可以根据比较界面不同快照间的差异分析内存问题。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b1/v3/_AQu7JPxQTST2lX4wEB63g/zh-cn_image_0000002594669688.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=B0E711A0A7B263CEF1AAEE7B2906399A4867C1BD82A75AC2613E20C77E19C1E2)

#### \[h2\]控制(Containment)

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

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/8/v3/RPcoSCKOTNCNb48DA7Cv3Q/zh-cn_image_0000002594829616.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=D08C71F1EE989A549094D92F55819D3197D6D47F197F113EC0FC88F277B5912F)

#### \[h2\]统计信息(Statistics)

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

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e8/v3/rwE9T6B4RTawv7w_D8Kd4A/zh-cn_image_0000002625189063.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=90B7609EA7F3CCBDDD3492D8D0EE23A46DA7673E5FD5F21C78E9F3948A5A108F)

#### 内存泄漏分析流程

1.  打开一个可能存在内存泄漏问题的页面并启用DevTools。下图展示的页面来自GitHub上的[memory-leak-simulation](https://github.com/Buchatech/JavaScript-Memory-Leak-Simulation)项目，该网页通过设置全局数组并不断向其推入'memory leak'字符串来模拟内存泄漏场景。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/69/v3/eHRNxowpSH2weGG0NbmJcg/zh-cn_image_0000002625109207.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=6E6A82E098B48EE08F06193C98C3A2B00B7B99BE525CDA40029658F672C0E76C)
    
2.  在性能界面录制可能导致内存泄漏的用户操作，以识别引起内存泄漏的用户操作或组件。下图显示，网页已加载完毕，但内存仍在持续上升，表明可能存在内存泄漏问题。对于包含大量动态组件和频繁DOM操作的网页，内存曲线可能呈起伏状态。持续观察内存起伏的最低值变化，若最低值逐渐上升，怀疑网页存在内存泄漏问题。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/12/v3/60npm3idQaqIHQSxC4AfHQ/zh-cn_image_0000002594669690.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=212DEA9ADA20AECC479A52A8A27597C5082F4EFD18034DF8DAD7CE216A35AA88)
    
3.  我们对这个网页进行第一次堆快照，发现Array占用了28M内存，基于该对象的内存占用显著高于正常值(通常在几MB范围内)，可以判断该对象可能存在内存泄漏问题。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b2/v3/C1EpoW8UQ8Ka7LUufDabtw/zh-cn_image_0000002594829618.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=C83A7BBA03528579F7B678ED4FC4B0EECF23A87F8C6427518C7A2AA9293C60F2)
    
4.  对网页进行可能会造成内存泄漏的操作，操作完成后进行第二次堆快照，然后选择两个快照间分配的对象，观察到Array构造器新产生约16MB内存占用。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/8/v3/66ePYTspQEChIgtWT5OK9g/zh-cn_image_0000002625189065.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=415087A960A4813A1C3367FE850D3FCD58F543A80DA0FCAACAA7B54806D5CA00)
    
5.  查看**比较(comparison)**，选择快照3并使用快照2作为比较对象，观察到Array构造器新产生了4030个对象，占用了16.1MB空间，但只释放了184B空间，根据此结果，确定内存泄漏发生在Array中。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6e/v3/V-_Po9DRQtm3lE4IzmHINQ/zh-cn_image_0000002625109209.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=8C1115C4E0DA0FC38DF898B5367532FCFFB1F011DDD5340EF28787C332264A74)
    
6.  录制1-2分钟的堆快照来获得包含时间轴的摘要视图，这与性能界面中的视图类似。使用此视图可以分析是哪个动作造成了内存占用的变化。录制快照时选择“时间轴上的分配情况”选项，点击录制。完成想要测试的动作后，停止录制即可生成内存堆时间轴视图。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6e/v3/AgfWkaF7TNqlvFrCj25DNQ/zh-cn_image_0000002594669692.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=1D5D6E51DCE94E293A86C373E1A7D47694EB5A38AFB363AF1980A474DA279BE6)
    
7.  在结果的时间轴上，使用左键滑动选择想要查看的区域，即可查看选定时间段内的内存分配情况。从下图中框选部分可以看到，在选定时间内，Array构造器产生了两千个新对象。利用该功能，可以明确不同操作对内存的影响。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/68/v3/pzfjmngKQLyCEv9iBIVbKg/zh-cn_image_0000002594829620.png?HW-CC-KV=V1&HW-CC-Date=20260612T073815Z&HW-CC-Expire=86400&HW-CC-Sign=D63504A6C96279BC9AA65C6B0CA7A51FB7771A6E4CA3D3A51DBD282647C7F89D)