背景:
某个客户有几千个会话, 说使用系统半小时后页面就很卡; 定位时打开控制台看到内存很高, 且不停在蹦 console 日志, 没定位到具体问题, 推测是客户联系人很多, 收发消息频繁, 存到系统/打印到控制台消息内容占内存多; 于是准备先禁掉 console.log 看看效果, 同时, 开始好好摸一摸咋定位页面内存泄漏问题
步骤:
找到两篇写的较详细 + 结合实例的定位内存泄漏教程: 使用 Chrome Devtools 分析内存问题, 借助 Microsoft Edge 分离的元素面板分析内存泄漏问题, 主要按第一篇操作(按第二篇整, edge 没显示分离元素, 只显示了分离元素数量…), 可以先看文章
-
打开 devtools, 打开内存标签页 + 性能监视器标签页
为方便查看, 我和教程里一样设置性能监视器分屏显示在下方
-
在内存标签页, 手动点击左上角回收垃圾按钮, 准备进行页面操作
本系统(vue2)有个功能是点击目录刷新右侧 router-view (先切换到空白页, 再 $router.replace 切回原页面), 所以页面操作就是点下目录刷新下, 这样刷新前后页面没变, 如果内存还飙升不降, 铁定有问题
-
执行页面操作, 完毕后再次点击回收垃圾按钮, 看看性能监视器显示的内存是否飙升不降
操作完毕后等一会儿, 页面没其他动作了在操作, 可以多试几次确定下是否有问题
-
如果确定有问题, 重复第二步 + 点击内存标签页左上角按钮拍摄堆快照, 拍摄完毕后重复第三步 + 拍摄快照2, 点击快照 2 选择对比快照 1, 等待比较完毕
拍摄时看下内存标签页右侧底部"选择 JavaScript 虚拟机实例", 注意别选中其他 worker , 第三方插件的实例了, 不然拍摄的是它们的快照
-
对比页面顶部, 搜索 detached , 点击列头按大小排序, 一般是 Detached HTMLDivElement 这个比较直观, 如果这个比较出来大小增大很多, 就用它来分析吧
-
点击展开 Detached HTMLDivElement , 选中第一个 HTMLDivElement (因为已经按大小排序了, 直接选第一个对大小影响最大的就行)
-
先看底下自动展开的内容里有没有眼熟的, 有的话最好, 直接定位到原因了
发现展开层级中有个 ‘gtm’ 相关的 js 对象占内存最大, 点击定位源码, 发现它里面有个属性直接指向了一个大 element , 导致此 element 未销毁, 网络标签页中屏蔽掉 gtm 相关 js , 问题解决一部分, 确定定位到原因了, 之后搜到了一篇文章Your website probably has a memory leak, 重写了 gtm 相关的 dataLayer(数组).push 方法, push 时替换原元素为 cloneNode , 成功解决
gtm 是 googleTagManager 追踪代码, 它定义 window.dataLayer 并持续 push 内容, 其中 event: ‘gtm.click’ 类的数组项似乎都有个 gtm.element 元素, 存着当时点击的 element , 导致内存泄漏
-
如果没有, 回到顶部右键当前查看的 HTMLDivElement , 存储为全局变量, 看看它属于页面上哪一块儿, 分析原因, over
分析方向: 属于哪个组件, 组件里有没有引用啥第三方插件可能导致组件销毁页面未销毁的, 实在定位不到, 代码全部注释了一块块儿逻辑解注释
其他:
之后发现另一个卡顿原因: 客户会话数过多, 频繁请求接口, 导致卡顿, 优化代码逻辑减少接口请求后解决