4种视图
- Summary 视图。该视图适合用于检查DOM节点泄露。按照构造函数名字分类的视图。查看每一个构造函数有多少个对象。
不能写匿名函数和匿名闭包:用于归因,假设应该函数内存泄露,可是又不知道名字,无疑加大难度html
使用技巧:再Class Filter中,搜索Detached
能够查看是否有分离的DOM。也能够搜索想要查看的构造器的名称react
而后看retainers窗口,第一行通常是引用该对象的元素。能够经过distance列来看,通常会比Detached
的节点上一层git
-
Comparison 视图。也是根据构造函数分类,比较两个快照。好比react的
FiberNode
增长多少,删除多少github -
Containment 视图。自上而下查看对象引用链。web
-
Dominators 视图 为何找不到
Dominators view
? 注意: Chrome Canary 版本 的DevTools中的Settings > experiments > Show advanced heap snapshot properties 开启,重启DevTools生效 不过根据这个提示也没找到chrome
概念
-
Distance:GC ROOTS 倒该对象的距离。从1开始antd
-
Shallow size : 对象自身大小闭包
-
Retained size:对象所引用的全部对象的大小。也就是假设该对象去除后,将会释放这么多内存chrome-devtools
-
Detached: 已经与HTML分离,可是Javascript仍然保留引用。说明没有清除干净,存在内存泄露。说一些例子函数
- html已被移除。可是Javascript仍然监听着事件,说明存在内存泄露
document.createElement
,Javascript端一直保存着
-
黄色背景对象:已经分离的DOM节点(Detached节点),可是仍被Javascript端引用着。可能存在DOM节点泄露
-
红色背景对象:已经分离的DOM节点(Detached节点),可是被黄色背景的DOM引用着。可能存在DOM节点泄露
注意: 在React中由于组件会切换显示/隐藏。因此会保留(retain)原来的DOM对象,也就是会存在Detached
的DOM是正常的;当切换导其余页面时就会被GC;只有不能被GC的Detached
DOM才算是内存泄露
Allocation Timeline 解决JS堆内存泄露
蓝色线是申请内存。若是很高能够排查
Allocation Samping 查看函数内存申请
遇到的坑
Chrome password控件不会释放内存
react使用 input password控件不会释放内存,子组件不释放,父组件页面就不会释放。 使用antd pro
的Password
组件,通过来回切换路由(页面)后,原先的页面依然存在(Summary页面查询名字),在summary的页面中会有不少个对象,而且只有一个是有distance
,其余都是横杠-
。将password
换成普通的input
就会正常被GC掉。最后有使用者发现其实这是chrome的BUG.
chrome console.log 会内存泄露
背景:有一个很大的表格react组件,由于调试用了console.log输出props
属性。而后切换路由,发现出现这个页面一直没有被GC回收!!而且distance仍是斜杠
最后去掉console的输出,GC正常。由于console.log会保持输出对象的引用不被GC回收,不然回收了怎么看内容调试呢。所以生产环境要去掉不必的console
例子
let leakObjects = []; function MyObject() {} for (let i = 0; i < 100000; ++i) { leakObjects.push(new MyObject()); } console.log(leakObjects); // chrome devtool > memory > heap snapshot > summary > class filter 输入 MyObject // 即使不引用也是不会被GC回收,出现内存泄露 leakObjects = null;
issues: Password input type causes memory leak #14962
Issue 967438: Memory leak with input type=password
其实火狐的工具也是很不错的 https://developer.mozilla.org/zh-CN/docs/Tools/Memory/Dominators_view