如何排查网页在哪里发生了内存泄漏?

news2024/11/28 0:42:43

今天我们来学习用 devtool 的 Performance 和 Memory 工具来找出网页哪里发生了内存泄漏。

Performace 面板

首先我们打开浏览器的 devtool,选择 Performance(性能)面板,然后将 Memory 选项勾选上。不勾选的话,就不会记录内存使用情况,内存泄漏分析就无从说起了。

然后进行性能数据收集:

1.点击左上角的 “录制” 按钮(一个灰色的圆形),或者点它旁边的 “刷新” 按钮,会重新加载页面并开始记录,这样就不用手动刷新然后手忙脚乱地点录制按钮了;2.在页面上执行可能发生内存泄漏的操作,比如打开一个弹窗,然后再关闭;3.差不多了就再点击 “录制” 按钮,结束录制,然后出现下面图片的结果。

查看内存指标

看看内存的使用情况。有这么几步:

1.选中要分析的范围;2.选中 Main(主线程)。只有选中的话,内存图表才能显示主线程对应的信息;3.查看内存图表的指标。

内存图表是一些折线图,记录了内存指标随时间发生的变化。这些内存指标有:JS 堆内存、Document 数、节点数、绑定监听器数量、GPU 内存。

点击它们可显示或隐藏对应的折线图。

对于 JS Heap(11.9MB - 25.6MB) ,它表示的是在当前时间范围内,JS 堆内存最小值为 11.9 MB,最大为 25.6 MB。

将光标悬停在折线图上,可以看到对应的值:

查看内存下限的变化

内存会增长是正常的现象。比如我们调用函数,会创建一些临时变量,导致内存升高。函数执行完,这些变量就没用了,但不会马上回收,而是会在适当的时机进行内存回收,将内存再降下去。

临时分配的短命内存我们并不关心,我们更关注的是一些常驻的内存,对应的要看的是 内存下限的变化

如果内存下限不断上升,说明常驻内存变大了。大多数情况下是正常的,比如:

1.调用函数,将函数返回的结果进行缓存;2.创建新的组件。也可能是内存泄漏了。

当怀疑是内存泄漏时,我们就可以使用 Memory 面板记录快照,做进一步的排查。

Memory 面板

打开 Memory 面板,点击左上角的 “录制按钮”,生成当前时刻的堆内存快照。然后通过快照了解 JS 对象的内存分布

Summary View

快照结果默认会展示为 概要视图(Summary View)

这个表格的表格项是基于构造函数进行归类的。可以看到有不少原生的构造函数,还有一堆闭包。

每个项有以下几个属性:

  • Constructor:构造函数。对于没有构造函数的字面量,用类似 (string)(array) 的表示;* Distance:到根节点的最短路径;* Shallow Size:自己占用的内存大小,不包括它引入的其他对象内存,单位为字节;* Retained Size:对象自己以及它引用的对象的内存,单位也是字节;* Object Count:对象数量,就是 Constructor 名旁边那个数字;上面是默认的 Summary View 视图。

除了它,我们还有其他的视图,可以像下面这样进行视图类型的切换。

Comparison View

比较视图(Comparison View)则是用来比较两个快照的变化

这里我选中了快照 3,然后将对比快照设置为 快照 1。

这个表格表示从快照 1 变成快照 3 发生的变化。没有发生变化的项不会进行展示。

字段有:

  • Constructor:构造函数;* #New:新增的对象数量;* #Deleted:删除的对象数量;* #Delta:总体上的对象变化数量;* Alloc.Size:分配的总内存;* Freed Size:释放了多少内存;* Size Delta:总体上的内存变化;### Containment View

该视图可以让我们从根节点为起点,往下去查看各种对象占用的内存,以及被创建的代码位置等信息。

字段:

  • Object:普通对象或者 DOM 节点:* Distance:到根节点的距离;* Shallow Size:对象大小,不计算引用的对象;* Retained Size:对象大小,但其引用的对象大小也计算在内;### Statistics View

圆环统计表。

各种内存类型的占总内存的百分比情况。

使用 Memory 面板注意事项

尽量减少干扰项的影响力。

1.分辨正常的内存变化会的干扰;2.注意开发环境的打包器热加载逻辑等的影响;3.生成环境的代码是混淆过的,一些构造器名字很奇怪,如果可以的话,本地打包一份没经过混淆过的代码做 debug。或者也可以 hover 看看对象结构猜测对应构造器,但效率不高。4.不要有浏览器插件,它们也占用和影响内存,可以用无痕浏览器。常见内存泄漏原因和排查

忘记及时取消监听器绑定

新手老鸟都容易犯的错误,就是 忘记及时取消监听器绑定。它会导致:

1.监听器函数中的对象迟迟不能释放,比如非常大的组件实例;2.绑定大量无用的监听器函数。怎么排查?

如果监听器是绑定到 DOM 中,我们可以不断执行可以看 Listener 数量的变化。

我写了个弹窗组件,它会在挂载时给 document.body 注册一个函数,然后这个函数会用到这个组件下的变量。但销毁时不取消注册。

打开 Performance 面板,录制,然后不停打开和关闭弹窗,然后结束录制。我们就能看这个 Listeners 的数量的变化,不断地变高那就是忘了。

也可以看看 Memoery 面板中 Comparison View 的快照对比中,EventListener 数量的变化:

具体是哪个,可以看 EventListener 下的最后几个对象。

点击这个蓝色的链接,就能跳到对应的代码位置:

此外,还可以用 Chrome 控制台提供的 getEventListeners(element) 方法,它会返回一个元素事件绑定的函数有哪些。这个方法不是标准方法,是 Chrome 自带的工具方法,只能在控制台上用。我们可以写个方法,从根节点往下找,找出绑定函数数量最多的节点,这个节点多得离谱那就大概率是忘了解绑。

如果不是 DOM 上的监听器,比如发布订阅库的事件集合,那就要看构造器对应对象数量的变化了。

闭包

闭包就是拿到函数 A 内的另一个函数 B,函数 B 会捕获到函数 A 作用域中的变量。

这个就导致了对一些对象的隐式引用,比如一个 DOM 元素。我们需要在不需要使用时将其设置为 null。

我们可以看看有没有什么 Detached 的元素。Detached 表示不在当前文档树上,如果持续增多,可能发生了内存泄漏。

说真的闭包是一个正常的特性,没理由和内存泄漏有关才是。

函数 B 被持有不销毁,自然它捕获的函数 A 中的变量就不能销毁,和对象里有一些属性,这些属性不能销毁没啥区别。函数 B 销毁了,对应的变量自然也就回收了。

有空我再研究下写篇专题。

console

“你到底都打印了些什么啊?”

还有个比较常见的就是,在开发的时候用 console 打印一些对象,合并到主分支又忘记去掉。这些对象是不会被回收的,因为开发者可能会去控制台看看这些对象的内容。这在打印大量大对象时会出性能问题。

排查方法很简单,去看 DevTool 的控制台输出了什么内容,看看有没有大对象

一些有助于 debug 的 console 是有必要的,但不要滥用。

集合类型的缓存爆炸

我们经常用对象、数组、Map、Set 等集合类型,去做数据的缓存。

当缓存大量对象时,会占用大量的内存,但其中有不少内容是不需要用的。对于前端来说,内存不像后端那样纯金寸土,动不动就是大批量数据要处理,缓存使用起来挺随意的。

对于缓存问题,还要要有点意识,我们可以:

1.使用 LRU 算法,将最久没使用的缓存移除,控制缓存数量;2.设置缓存过期时间;3.对于临时缓存,考虑使用 WeakMap 和 WeakSet,它们会在 GC 时强制回收;这些就没啥好分析的,就看看内存下限变化,某些对象是否变大变多了。

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/345271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

火爆全网的ChatGPT,可以自己上手搭建了。

没有人不知道ChatGPT了吧? ChatGPT,发布于2022年11月30日,来自人工智能研究实验室OpenAI,是一款全新聊天机器人模型,一款人工智能技术驱动的自然语言处理工具。 5天用户破百万,2个月活跃用户破亿。ChatGP…

大学生常用python变量和简单的数据类型、可迭代对象、for循环的3用法

文章目录变量和简单的数据类型下划线开头的对象删除内存中的对象列表与元组debug三酷猫钓鱼记录实际POS机小条打印使用循环找乌龟可迭代对象📗理解一📘理解二2️⃣什么是迭代器✔️注意3️⃣迭代器对象4️⃣有关迭代的函数for循环的3用法🌸I …

C++ 算法主题系列之贪心算法的贪心之术

1. 前言 贪心算法是一种常见算法。是以人性之念的算法,面对众多选择时,总是趋利而行。 因贪心算法以眼前利益为先,故总能保证当前的选择是最好的,但无法时时保证最终的选择是最好的。当然,在局部利益最大化的同时&am…

Seata-Server分布式事务原理加源码 (五) - Seata配置Nacos注册中心和配置中心

Seata配置Nacos注册中心和配置中心 Seata支持注册服务到Nacos,以及支持Seata所有配置放到Nacos配置中心,在Nacos中统一维护; 高可用模式下就需要配合Nacos来完成 具体配置如下 注册中心 Seata-server端配置注册中心,在registr…

【Android学习】下载jar慢和gradle慢的情况

目录 问题出现的原因 解决方法 解决Gradle下载问题:手动安装 解决jar包下载慢问题:更改下载源 问题出现的原因 国内访问谷歌被墙导致访问速度慢或者干脆无法下载 解决方法 解决Gradle下载问题:手动安装 访问官网Gradle | Release Candi…

配置可视化-基于form-render的无代码配置服务(一)

背景 有些业务场景需要产品或运营去配置JSON数据提供给开发去使用(后面有实际业务场景的说明),原有的业务流程,非开发人员(后面直接以产品指代)把数据交给开发,再由开发去更新JSON数据。对于产…

【LeetCode】打家劫舍 III [M](递归)

337. 打家劫舍 III - 力扣(LeetCode) 一、题目 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。 除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识…

山东大学2022操作系统期末

接力:山东大学2021操作系统期末 2022—2023山东大学计算机操作系统期末考试回忆版 简答题(4 10 points) (1)用户态,核心态是什么 (2)这种区分对现代操作系统的意义 (3)printf(“…

基于RK3399+STM32+PID的四轴飞行器跟踪与控制系统设计

系统硬件的总体方案设计 要设计一款具有跟踪功能且飞行稳定的四轴飞行器跟踪系统,首先要保证系 统硬件平台的功能稳定。系统各模块具有不同功能,所以需要根据各模块功能与 性能,进行芯片的选取与硬件电路设计,使系统在经济性、生产…

优维低代码:Legacy Templates 构件模板

优维低代码技术专栏,是一个全新的、技术为主的专栏,由优维技术委员会成员执笔,基于优维7年低代码技术研发及运维成果,主要介绍低代码相关的技术原理及架构逻辑,目的是给广大运维人提供一个技术交流与学习的平台。 连载…

镜像恒流源电路分析

在改进型差动放大器中,用恒流源取代射极电阻RE,既为差动放大电路设置了合适的静态工作电流,又大大增强了共模负反馈作用,使电路具有了更强的抑制共模信号的能力,且不需要很高的电源电压,所以,恒…

Chatgpt取代客服?取代客服的其实另有其人

近来,一款聊天机器人ChatGPT刷爆全网,这也让不少人发出疑问:人工智能真的能大规模取代人类吗?其实,人工智能在很多行业比如电商、金融、医疗教育和制造业等领域已经有许多尝试和应用,最常见的就是大家在生活…

研报精选230214

目录 【行业230214艾瑞股份】中国增强现实(AR)行业研究报告【行业230214国信证券】信息安全深度剖析5:密评和信创双催化,密码产业开启从1到N【行业230214民生证券】磁性元器件深度报告:乘新能源之风,磁性元…

【数据结构】基础:图的遍历实现(附C++源代码)

【数据结构】基础:图的遍历实现(附C源代码) 摘要:将会在数据结构专题中开展关于图论的内容介绍,其中包括四部分,分别为图的概念与实现、图的遍历、图的最小生成树以及图的最短路径问题。本文将介绍图的遍历…

Python实现视频自动打码功能,避免看到羞羞的画面

前言 嗨呀嗨呀,最近重温了一档综艺节目 至于叫什么 这里就不细说了 老是看着看着就会看到一堆马赛克,由于太好奇了就找了一下原因,结果是因为某艺人塌房了…虽然但是 看综艺的时候满影响美观的 咳咳,这里我可不是来教你们如何解…

卡诺图化简

1.相关概念 最小项:函数的某个乘积项包含了函数的全部变量(原变量或反变量的形式),且每个变量仅出现一次,则这个乘积项为该函数的一个标准积项。 最小项中的原变量记为1,反变量记为0,当变量顺序…

C++STL剖析(九)—— unordered_map和unordered_multimap的概念和使用

文章目录1. unordered_map的介绍和使用🍑 unordered_map的构造🍑 unordered_map的使用🍅 insert🍅 operator[ ]🍅 find🍅 erase🍅 size🍅 empty🍅 clear🍅 sw…

程序环境和预处理详解

文章目录一、程序环境1.1 - 翻译环境1.1.1 - 编译1.1.1.1 - 预编译(预处理)1.1.1.2 - 编译1.1.1.3 - 汇编1.1.2 - 链接1.2 - 执行环境二、预处理详解2.1 - 预定义符号2.2 - #define2.2.1 - #define 定义标识符2.2.1.1 - 语法2.2.1.2 - 建议2.2.2 - #defi…

AI极大地改变了知识创造与分发的逻辑

AI改变了~知识创造、分发的逻辑 细想一下这是恐怖的 已经传导出给教育的压力 趣讲大白话:AI机器人成了随身专家 *********** 1.以前靠秀才创造、分发知识 2.后来是教育体系为主 3.再后,互联网平台聚合和分发 4.将来可能大部分是机器人创造、分…

Xshell和Xftp的下载和在linux虚拟机中的使用

Xshell和Xftp的下载和在linux虚拟机中的使用一、Xshell和Xftp简介XshellXftp二、 Xshell和Xftp下载三、Xshell和Xftp安装Xshell安装Xftp安装四、 Xshell和Xftp使用找到linux虚拟机的ip地址Xshell的使用Xftp的使用一、Xshell和Xftp简介 Xshell Xshell 是一个强大的安全终端模拟…