使用 chrome 排查内存泄露
内存分析使用的工具包括 chrome 任务管理器、chrome 时间轴(低版本是 Timeline,高版本对应 performance)、chrome memory(低版本是 chrome profiles,主要用 JS 堆快照、JS 堆动态分配时间轴)
chrome 的工具里提供了很多种方式去排查明确内存情况,但我觉得会其中的一些就够了,就好像使用 js API 一样,我们会 js API 里的某些就可以了,其他的不会,也可以使用我们懂的进行模拟,或快速上手其他 API。
而我喜欢使用Head snapshot
生成某个时刻的内存快照,然后多进行几次进行比较,得出我的结果。
使用 Summary 如图
Constructor:构造函数,节点下的对象都是由改构造函数创建而来。
Distance:与根节点的距离。
Objects Count:对象个数及百分占比。
Shallow size:对象的直接内存总数,直接内存是指对象自身占用的内存大小。
Retained size:对象的最大保留内存,保留内存是指对象被删除后可以释放的那部分内存。
点击展开构造函数,可以看到所有构造函数相关的对象实例,@后面的数字是该对象实例的唯一标识符。
使用比较快照的,comparison
Contructor - 表示使用此构造函数创建的所有对象
Distance - 显示使用节点最短简单路径时距根节点的距离
Shallow Size - 显示通过特定构造函数创建的所有对象浅层大小的总和。浅层大小是指对象自身占用的内存大小(一般来说,数组和字符串的浅层大小比较大)
Retained Size - 显示同一组对象中最大的保留大小。某个对象删除后(其依赖项不再可到达)可以释放的内存大小称为保留大小。
#New - Comparison 特有 - 新增项
#Deleted - Comparison 特有 - 删除项
#Delta - Comparison 特有 - 增量
Alloc. Size - Comparison 特有 - 内存分配大小
Freed Size - Comparison 特有 - 释放大小
Size Delta - Comparison 特有 - 内存增量
常见的顶层构造函数:
(global property):全局对象和普通对象的中间对象,和常规思路不同。比如在 Window 上定义了一个 Person 对象,那么他们之间的关系就是[global] => (global property) => Person。之所以使用中间对象,是出于性能的考虑。
(closure):使用函数闭包的对象。
(array, string, number, regexp):一系列对象类型,其属性指向 Array/String/Number/Regexp。
HTMLDivElement/HTMLAnchorElement/DocumentFragment:元素的引用或者代码引用的指定文档对象。
在 Class filter(类过滤器)文本框中输入 Detached 可以搜索分离的 DOM 树。
一般来说排查过程是一个细心的活,因为 chrome 的工具提供了很多信息给我们,但代码方面可能不是自己写的,不能很明确这部分是否是真的有问题,因此我们只能根据 chrome 提供的文件名、方法、实例对象、DOM 节点等等去尝试这部分变化是否能给应用带来改进,而我觉得最常出问题应该是闭包这类。