浏览器内存泄漏排查指南

news2024/12/26 0:35:30

1、setTimeout执行原理

使用setInterval/setTimeOut遇到的坑 - 掘金

2、Chrome自带的Performance工具

当我们怀疑页面发生了内存泄漏的时候,可以先用Performance录制一段时间内页面的内存变化。

  • 点击开始录制
  • 执行可能引起内存泄漏的操作
  • 点击停止录制

如果录制结束后,看到内存的下限在不断升高的话,你就要注意了 —— 这里有可能发生了内存泄漏。

除了内存增长曲线,Nodes(Dom节点数曲线)、Document曲线以及Listener曲线也同样值得关注,有时候它们对内存问题的定位也很有帮助。

你怀疑发生了内存泄漏的时候,你就可以用Memory面板来进一步定位泄漏的源头了。

3、Chrome自带的Memory工具

从Memory的主界面开始,点击左上角的圆点就可以记录下当前的堆内存快照(heap snapshot)了。

  1. 打开DevTools, 切换至Memory面板
  2. 先记录一个堆内存快照
  3. 执行可能发生泄漏的操作
  4. 再记录一个堆内存快照
  5. 重复执行多几遍步骤3,4
  6. 选择最后一个堆内存快照,找到顶栏的“All objects”, 切换至”Objects allocated between snapshots 1 and 2”(也可以对2,3执行同样的操作)

切换后,你就能看到两个快照之间新生成的对象。你可以选择其中一项点开,看看它的retaining tree里面保留了哪些对象没有释放。

4、经验说明

4.1 为什么我的内存快照记录下来之后看不懂,还出现了很多奇怪的变量

除去教程里demo代码比较简单之外,提前准备好一个合理的debug环境也是很重要的。这里我列举了4点个人觉得对debug内存问题很有帮助的措施:

1. 尽量使用没有混淆的代码:打包后的代码往往经过了混淆和压缩,在生产环境上这是必要的,但在debug时却会成为我们的绊脚石,不便于阅读。

2. 排查问题时使用production模式编译出来的代码:Dev模式下往往会开启一些方便开发的特性,例如热更新等。但它们可能会占用一部分的内存,影响到内存问题的排查,所以建议还是使用production模式编译出来的代码进行问题排查。

3. 屏蔽所有浏览器插件:屏蔽浏览器插件最快的方式就是打开无痕窗口。浏览器插件给我们带来很多便利,但插件注入的额外逻辑有时也会影响内存问题的排查。例如vue-devtools会记录下每一个vuex mutaions,导致内存无法释放。

4. 在现场打内存快照,便于跳转到源代码所在行:尽管devTools记录下来的内存快照文件可以单独加载展示,但还是建议在记录下内存快照的时候“趁热”分析,因为这时还能从retaining tree上跳转到代码所在行,有时候对定位问题也很有帮助。

4.2 快照里有一些“Detached DOM tree”,是什么意思

一个DOM节点只有在没有被页面的DOM树或者Javascript引用时,才会被垃圾回收。当一个节点处于“detached”状态,表示它已经不在DOM树上了,但Javascript仍旧对它有引用,所以暂时没有被回收。通常,Detached DOM tree往往会造成内存泄漏,我们可以重点分析这部分的数据。

4.3 常见的内存泄漏场景有哪些

  1. console导致的内存泄漏 因为打印后的对象需要支持在控制台上查看,所以传递给console.log方法的对象是不能被垃圾回收的。我们需要避免在生产环境用console打印对象。
  2. 框架配合第三方库使用时,没有及时执行销毁 这点可以参考vue cookbook里的例子:避免内存泄漏 — Vue.js 中文文档
  3. 被遗忘的定时器 例如在组件初始化的时候设置了setInterval,那么在组件销毁之前记得调用clearInterval方法取消定时器。
  4. 没有正确移除事件监听器(各种EventBus, dom事件监听等) 这应该是最容易犯的一个错误,无论新手老手都有可能栽在这里。
    特征:performance里,监听器数量会持续上升

补充说明:

尽管大部分同学都会有主动移除监听器的观念,但如果姿势不对,可能依旧会造成内存泄漏。下面是一个真实案例:

// 版本一
mounted() {
    window.addEventListener('resize', debounce(this.handleWidthChange, 100))
},
beforeDestroy() {
    window.removeEventListener('resize', debounce(this.handleWidthChange, 100)) 
}

乍一看好像写的还不错,有及时移除监听器,对resize这种频繁触发的事件也加了debounce处理。但其实这段代码就导致了内存泄漏:每次调用debounce(this.handleWidthChange, 100)时, 其实都会返回一个新的函数,导致addEventListener和 removeEventListener方法传入的回调函数已经不是同一个回调函数,监听器没有被正确移除,内存泄漏。 




 修改后的代码如下:

data() {
    return {
        debounceWidthChange: null
    }
},
mounted() {
    this.debounceWidthChange = debounce(this.handleWidthChange, 100)
    window.addEventListener('resize', this.debounceWidthChange)
},
beforeDestroy() {
    window.removeEventListener('resize', this.debounceWidthChange)  
}

5、总结

简单总结一下排查内存泄漏的常见流程:

  1.  用performance面板记录操作一段时间内的内存变化,找出可能发生内存泄漏的操作。
  2.  用“three snapshot”技巧,记录下发生泄漏前后的内存快照。
  3.  用comparison视图对泄漏前后的内存快照进行比较,找出泄漏的对象。
  4. 重点关注 Vue Component, Detached HTMLDivElement等Constructor。

备注:

 手把手教你排查Javascript内存泄漏 - 知乎

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

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

相关文章

C# OpenCvSharp DNN Gaze Estimation 视线估计

目录 介绍 效果 模型信息 项目 代码 frmMain.cs GazeEstimation.cs 下载 C# OpenCvSharp DNN Gaze Estimation 介绍 训练源码地址:https://github.com/deepinsight/insightface/tree/master/reconstruction/gaze 效果 模型信息 Inputs ----------------…

利用牛顿方法求解非线性方程(MatLab)

一、算法原理 1. 牛顿方法的算法原理 牛顿方法(Newton’s Method),也称为牛顿-拉弗森方法,是一种用于数值求解非线性方程的迭代方法。其基本思想是通过不断迭代来逼近方程的根,具体原理如下: 输入&#…

菜单栏应用管理 -- Bartender 4

Bartender 4是一款旨在优化和简化Mac菜单栏管理的强大工具。它具有以下特色功能: 组织和管理菜单栏图标:Bartender 4允许用户轻松组织和管理菜单栏中的图标,可以隐藏不常用的图标,保持菜单栏的整洁和简洁。同时,用户还…

RAG——应用——七个最常见的故障点

近日,国外研究者发布了一篇论文《Seven Failure Points When Engineering a Retrieval Augmented Generation System》,探讨了在实际工程落地RAG应用过程中容易出的七类问题。 论文地址:https://arxiv.org/pdf/2401.05856.pdf 一、丢失内容&…

MacOS安装反编译工具JD-GUI以及解决无法打开的问题

目录 一.下载地址 二.安装 三.问题 四.解决办法 1.显示包内容 2.找到Contents/MacOS/universalJavaApplicationStub.sh 3.修改sh文件 4.保存后再次打开即可 一.下载地址 Java Decompiler 二.安装 将下载下来的 jd-gui-osx-1.6.6.tar 解压,然后将 JD-GUI.a…

提升工作效率,畅享便捷PDF编辑体验——Adobe Acrobat Pro DC 2023

作为全球领先的PDF编辑软件,Adobe Acrobat Pro DC 2023将为您带来前所未有的PDF编辑体验。无论您是个人用户还是企业用户,Adobe Acrobat Pro DC 2023将成为您提高工作效率、简化工作流程的得力助手。 一、全面编辑功能 Adobe Acrobat Pro DC 2023提供了…

如何写出让用户身临其境的画面感文案?

许多小伙伴在写文案时经常会碰到这样的困境,就是自己写得文案用了大量辞藻但是没有效果。因为在信息爆炸的时代下,用户天生不喜欢抽象的东西,只有具象化的东西才能让人不费脑子,所以我们要尽可能的将文案视觉化,去写有…

分享外贸人的一些趣事

某日晚上突然失眠,然后就莫名地回忆起与一些客户沟通的过往,有时候感觉哭笑不得,有的时候又感觉无可奈何。 于是想总结一下在和客户沟通中的那种小惊喜,小惊讶,小郁闷,以及还有一些小小的感动。 先说一说…

数据防泄密方案公司(dlp数据防泄密厂商排名)

在当今数字化时代,数据已经成为了企业最重要的资产之一。然而,随着企业信息化的不断深入,数据泄露的风险也越来越大。为了保护企业的核心数据,越来越多的企业开始重视数据防泄密工作,并寻求专业的数据防泄密方案提供商…

Python入门到精通(五)——Python数据容器

Python数据容器 前言 一、list 列表 1、定义 2、列表的下标索引 3、常用操作 4、列表的遍历 二、tuple 元组 1、定义 2、常用操作 三、str 字符串 1、定义 2、常用操作 四、容器序列的切片 五、set 集合 1、定义 ​编辑 2、常用操作 六、dict 字典、映射 1、…

数据治理之路读书笔记

数据治理之路 一、数据治理的国际实践 美国——探索构建数据资产化管理体系(奥巴马2012《数字政府战略》、2020年《美国国防部数据战略》) 欧盟——从数据价值链到单一数据市场(2013《欧洲数据价值链战略》、2015《欧洲数字单一市场战略》、…

【Python笔记-设计模式】单例模式

一、说明 单例是一种创建型设计模式,能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。 (一) 解决问题 维护共享资源(数据库或文件)的访问权限,避免多个实例覆盖同一变量,引发程序崩溃。 …

STM32入门教程-2023版【5-1】中断执行流程

关注 点赞 不错过精彩内容 大家好,我是硬核王同学,最近在做免费的嵌入式知识分享,帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作! 二、中断执行流程 (1)中断程序的执行流程 左边第一个图中,从上…

【MySQL 流浪之旅】 第六讲 浅谈 MySQL 锁

系列文章目录 【MySQL 流浪之旅】 第一讲 MySQL 安装【MySQL 流浪之旅】 第二讲 MySQL 基础操作【MySQL 流浪之旅】 第三讲 MySQL 基本工具【MySQL 流浪之旅】 第四讲 MySQL 逻辑备份【MySQL 流浪之旅】 第五讲 数据库设计的三个范式 目录 系列文章目录 一、什么是锁&#x…

网络安全|重大失误!微软被盗测试账号拥有公司Office 365管理员权限

微软网络近期遭黑客入侵,高管电子邮件被监视长达两个月。 一位研究员表示,黑客通过获取一个拥有管理员权限的老旧测试帐号的访问权限来实施入侵,这是微软犯下的重大失误。 微软在1月25日(上周四)发布第二篇公告&…

Android Studio项目——TCP客户端

目录 一、TCP客户端UI 1、UI展示 2、xml代码 二、TCP客户端数据发送 三、TCP客户端数据接收 一、TCP客户端UI 1、UI展示 2、xml代码 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.…

JAVA双列集合Map的特点

一次存一对元素&#xff0c;分别是 键 和 值&#xff0c;他们是一 一对应的&#xff1a;其中&#xff1a;键不可以重复&#xff0c;值可以重复这一对数据叫键值对、键值对对象、或 Entry Map 的体系结构&#xff1a; Map的常见API&#xff1a; 方式的实现&#xff1a;注意 Map …

UDP通信以及本地套接字

1. UDP 1.1 UDP 通信&#xff1a; UDP服务端创建出来的套接字不是监听套接字&#xff0c;直接就是通信套接字。 #include <sys/types.h> #include <sys/socket.h> ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *de…

网络原理-TCP/IP(1)

应用层 我们之前编写完了基本的java socket, 要知道,我们之前所写的所有代码都在应用层中,都是为了完成某项业务,如翻译等.关于应用层,后面会有专门的讲解,在此处先讲一下基础知识. 应用层对应着应用程序,是程序员打交道最多的一层,调用系统提供的网络api写出的代码都是应用层…

正式阶段高等数学复习之不定积分

不定积分这部分是为后面的定积分做准备的&#xff0c;整体上的框架可以分为2&#xff08;定义&#xff09;3&#xff08;计算方式&#xff09;3&#xff08;能积出来的三个函数&#xff09; 1、不定积分的概念&#xff1a;求某一个函数的不定积分就是求这个函数的原函数&#…