三行代码,修复 DOM 内存泄露

前言

彦祖们,内存泄露应该是前端老生常谈的话题了

但是我们往往停留在理论层面,应付面试官,却十分缺少实战机会

本文是笔者在业务开发中遇到的一次真实案例,以此作为分享

技术栈:vue2(业务限制,未使用 keep-alive)

先看下 vue 官方文档

https://v2.cn.vuejs.org/v2/cookbook/avoiding-memory-leaks.html#%E7%AE%80%E4%BB%8B

场景

业务场景非常简单,就是两个 tab 页面互相切换,但是业务终端不是 pc

而是我们工业互联网业务中的工控机

因为可执行内存只有 1g,所以会经常出现卡顿的情况

彦祖们可以想象成那种医院挂号的终端

场景复现

操作流程

彦祖们,看下我此时的界面(主要关注下 DOM节点)

  1. 查看站点组情况

此时是 846

  1. 点击 单设备界面(单机界面)

发现此时的 DOM节点 增加到了 1587

当然这是正常现象

多出来的节点个数不就是我这个 单机界面 渲染的节点个数吗?

  1. 回到 站点组界面

惊人的发现 DOM 节点个数飙升到了 2862

  1. 不断来回切换

在笔者来回切换了五六次之后,此时节点个数来到了 5477

排查问题

猜想

我们初步猜想是 单机界面 存在节点内存泄露,那么该如何来证明这个猜想呢?

DevTools 介绍

我们需要借助 chrome devtools 来排查这个问题

  1. 打开 devtools 切到 内存 tab (英文版自行翻译)

2 . 选取 时间轴上的分配插桩

3 . 点击回收垃圾(每次录制前需要手动回收,以保证数据准确)

  1. 在我们的 单机界面 点击开始录制

  1. 点击结束录制,我们能看到时间桩上会分布 蓝色/灰色 的柱状图

柱状图的分布展示了新内存分配时机

蓝色部分表示目前还占用的内存

灰色部分表示目前已被回收的内存

此案例中我们主要关心的是内存分布区域的构造函数

我们检测下有没有 Vue组件泄露

开始录制时间桩

下面我们来模拟下业务中的场景

也就是站点组 单机界面来回切换,生成内存分布图

分析时间桩

  1. 我们利用左右两边的框选工具,定位到第一次切换到单机界面的柱状图

此时我已经切到了 站点组,但是蓝色区域还有大部分没有被回收,让我们来看看是否有单机界面的内存泄露

  1. 过滤出 Vue

一个个检查下,是否有哪个组件只存在单机界面的但是没有被回收

这个 .alter-message 笔者全局搜了一下

并确保只有在 单机界面 使用

前文已经提到,业务中未使用 keep-alive 进行缓存

那么 vue 应该帮我们销毁这个组件了呀

  1. 查看组件详情

我们来深入看下这个组件的信息,发现 vue 的确已经 destroy

这就很奇怪了,难道是所谓的 游离节点(https://juejin.cn/post/6984188410659340324#heading-5)?

不要慌,我们点击组件下面会展示内存分布详情

有些可能无法定位到代码文件,比如这种

这时候笔者就把 26 个泄露的文件一个个检查了一遍…(如果有更好的方式,欢迎评论区留言)

  1. 查看代码

那么我们就进去看看代码,一探究竟,发现以下三处可疑的地方

一步步定位到这两段代码,彦祖们应该已经发现问题所在了

插入一段八股文

此时不禁想起了这段八股文

面试官:造成内存泄露的情况有哪些?

彦祖: 未正确使用闭包 | 事件监听器未移除 | 定时器忘记清理 | 使用插件时,未销毁 | 意外的使用全局变量未回收 | console.log 未清除

回到正题

没错,我们这里就是命中了三个场景

  1. 事件监听器未移除

  2. 定时器忘记清理

  3. 使用 echarts 时,未销毁

导致堆内存不知道你什么时候会销毁这个事件,这个定时器有没有用它也不知道啊~

这样一来也就长期劫持了对 vue组件 的引用

也就是说每次进入单机界面 都需要开辟新的内存以支持组件的渲染

看下这张图

如果一个界面中某个组件未被完全移除

那么整个界面的所有组件所占用的内存都不能被完全释放

验证猜想

其实以上种种都是我们的猜想

接下来我们加上以下三行代码

  1. 移除全局事件监听
window.removeEventListener('closeException',this.xxx)   
  1. 移除全局定时器
clearInterval(this.timeInterval)   
  1. 销毁 echart 实例
this.myChart.dispose()   

再来抓一下内存分布

会发现已经没有泄露的 vue component

并且 DOM 节点 会被回收到 870 不会重复上升

改动3行代码,完美收工,走一个 998 🥳

坑点

彦祖们,补充一个坑点,在调试过程中,最好把 console 全去掉

笔者就在调试过程中遇到了一个坑,发现了这行代码

是的,打印了一下 vue 实例

console.log('实例', this)   

结果导致内存怎么都回收不了

给问题定位带来了重大的干扰

不过这也完美解释了为什么 console.log 为什么会导致内存泄露

总结

总结一下,如果彦祖们怀疑 A 页面有内存泄露,那么测试步骤如下

1.打开内存监视

2.A B A B 来回切换

3.关键!!!最后停留在 B 页面(不然 A 页面渲染了就会导致无法回收),停止内存监视

`黑客&网络安全如何学习

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

1.学习路线图

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。

(都打包成一块的了,不能一一展开,总共300多集)

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。

还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

优快云大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值