Memlab 是一款 E2E 测试和分析框架,用于发现 JavaScript 内存泄漏和优化机会。

MemlabJavaScript 的内存测试框架。它支持定义一个测试场景(使用 Puppeteer API),教 Memlab 如何与您的单页应用程序(SPA)交互,Memlab 可以自动处理其余的内存泄漏检查:

  • 与浏览器交互并获取 JavaScript 堆快照
  • 分析堆快照并过滤掉内存泄漏
  • 聚合和分组类似的内存泄漏
  • 生成用于内存调试的保留器跟踪

安装 Memlab

npm install -g memlab
memlab help

在 Demo App 中检测泄漏

使用 Memlab 检测分离的 DOM 元素的教程。Demo 源码:

设置示例 Web App

当您单击 “Create detached DOMs” 按钮时,Demo app 会泄漏分离的 DOM 元素。每次单击都会创建 1024 个分离的 DOM 元素,这些元素由 window 对象引用。

// @nolint

import Link from 'next/link';
import React from 'react'; export default function DetachedDom() { const addNewItem = () => {
if (!window.leakedObjects) {
window.leakedObjects = [];
}
for (let i = 0; i < 1024; i++) {
window.leakedObjects.push(document.createElement('div'));
}
console.log('Detached DOMs are created. Please check Memory tab in devtools')
}; return (
<div className="container">
<div className="row">
<Link href="/">Go back</Link>
</div>
<br />
<div className="row">
<button type="button" className="btn" onClick={addNewItem}>
Create detached DOMs
</button>
</div>
</div>
);
}

源文件:packages/e2e/static/example/pages/examples/detached-dom.jsx

1. 克隆仓库

要在本地机器上运行 demo,请克隆 memlab github 存储库

git clone git@github.com:facebookincubator/memlab.git

2. 运行示例 App

从 Memlab 项目的根目录运行以下命令:

cd packages/e2e/static/example
npm install
npm run dev

这将启动一个示例 Nextjs app。让我们通过从浏览器访问 http://localhost:3000 来确保它正在运行:

这里测试的是 Example 1

查找内存泄漏

1.创建一个场景文件

// @nolint
// memlab/packages/e2e/static/example/scenario/detached-dom.js
/**
* 我们要运行的场景的初始 `url`。
*/
function url() {
return "http://localhost:3000/examples/detached-dom";
} /**
* 指定 memlab 应如何执行您要测试该 action 是否导致内存泄漏的 action。
*
* @param page - Puppeteer's page object:
* https://pptr.dev/api/puppeteer.page/
*/
async function action(page) {
const elements = await page.$x(
"//button[contains(., 'Create detached DOMs')]"
);
const [button] = elements;
if (button) {
await button.click();
}
// 从 memlab 清理外部引用
await Promise.all(elements.map(e => e.dispose()));
} /**
* 指定 memlab 应如何执行将重置您在上面执行的 action 的 action。
*
* @param page - Puppeteer's page object:
* https://pptr.dev/api/puppeteer.page/
*/
async function back(page) {
await page.click('a[href="/"]');
} module.exports = { action, back, url };

这个文件在 packages/e2e/static/example/scenario/detached-dom.js

2.运行 memlab

这可能需要几分钟:

cd packages/e2e/static/example
npm run dev # 注意启动 Demo
memlab run --scenario scenarios/detached-dom.js

3.调试泄漏跟踪

对于每个泄漏的对象组,memLab 打印一个具有代表性的泄漏跟踪。

让我们从上到下分解结果:

第 1 部分:浏览器交互面包屑显示了按照我们的场景文件中指定的方式执行的浏览器交互(导航)memlab

  • page-load[6.5MB](baseline)[s1] - 初始页面加载时 JavaScript 堆大小为 6.5MBbaseline 堆快照将在磁盘上保存为 s1.heapsnapshot
  • action-on-page[6.6MB](baseline)[s2] - 单击 “Create detached DOMs” 按钮后,堆大小增加到 6.6MB
  • revert[7MB](final)[s3] - 在离开触发内存泄漏的页面后,该网页最终达到了 7MB。

第 2 部分:泄漏跟踪的总体摘要

  • 1024 leaks - 有 1024 个泄漏的对象。example app 的第 12 行在 for 循环中创建了 1024 个分离的 DOM 对象。
  • Retained size - 泄漏对象集群的聚合保留大小为 143.3KB(内存泄漏根据保留跟踪的相似性分组在一起)。

第 3 部分:每个泄漏簇的详细代表泄漏跟踪

泄漏跟踪是从 GC 根(垃圾收集器遍历堆的堆图中的入口对象)到泄漏对象的对象引用链。跟踪显示泄漏的对象为何以及如何在内存中仍然保持活动状态。 打破引用链意味着泄漏的对象将不再可以从 GC 根访问,因此可以进行垃圾回收。

通过从原生 Window(即 GC 根)向下逐个跟踪泄漏跟踪,您将能够找到应该设置为 null 的引用(但这不是由于bug 引起的)。

  • map - 这是正在访问的对象的 V8 HiddenClass(V8 在内部使用它来存储有关对象形状的元信息和对其原型的引用 - 在此处查看更多信息)- 在大多数情况下,这是 V8 实现细节,可以忽略。

  • prototype - 这是 Window 类的实例。
  • leakedObjects - 这表明 leakedObjectsWindow 对象的一个属性,大小为 148.5KB,指向一个 Array 对象。
  • 0 - 这表明分离的 HTMLDIVElement(即当前未连接到 DOM 树的 DOM 元素)被存储为leakedObjects 数组的第一个元素(由于显示所有 1024 条泄漏痕迹是压倒性的,Memlab 只打印一个具有代表性的泄漏痕迹。即属性 0 而不是属性 0->1023)

简而言之,从 Window 对象到泄漏对象的泄漏跟踪路径为:

[window](object) -> leakedObjects(property) -> [Array](object)
-> 0(element) -> [Detached HTMLDIVElement](native)

与示例中的泄漏代码匹配:

window.leakedObjects = [];
for (let i = 0; i < 1024; i++) {
window.leakedObjects.push(document.createElement('div'));
}

更多

Memlab,一款分析 JavaScript 堆并查找浏览器和 Node.js 中内存泄漏的开源框架的更多相关文章

  1. JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记1

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] 第 3 章 用 JavaScri ...

  2. Chrome 浏览器垃圾回收机制与内存泄漏分析

    Chorme 浏览器中的垃圾回收和内存泄漏 垃圾回收 通常情况下,垃圾数据回收分为手动回收和自动回收两种策略. 手动回收策略,何时分配内存.何时销毁内存都是由代码控制的. 自动回收策略,产生的垃圾数据 ...

  3. js的内存泄漏场景、监控以及分析

    内存泄漏 Q:什么是内存泄漏? 字面上的意思,申请的内存没有及时回收掉,被泄漏了 Q:为什么会发生内存泄漏? 虽然前端有垃圾回收机制,但当某块无用的内存,却无法被垃圾回收机制认为是垃圾时,也就发生内存 ...

  4. JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记3

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] JavaScript.jQuer ...

  5. JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记2

    技术很多,例子很多,只好慢慢学,慢慢实践!!现在学的这本书是[JavaScript实战----JavaScript.jQuery.HTML5.Node.js实例大全] JavaScript.jQuer ...

  6. Node.js中针对中文的查找和替换无效的解决方法

    Node.js中针对中文的查找和替换无效的解决方法.   //tags的值: tag,测试,帖子 var pos1 = tags.indexOf("测"); //这里返回-1 ta ...

  7. 编写浏览器和Node.js通用的JavaScript模块

    长期以来JavaScript语言本身不提供模块化的支持, ES6中终于给出了 from, import等关键字来进行模块化的代码组织. 但CommonJS.AMD等规范已经被广为使用,如果希望你的Ja ...

  8. JavaScript -- 时光流逝(六):js中的正则表达式 -- RegExp 对象

    JavaScript -- 知识点回顾篇(六):js中的正则表达式 -- RegExp 对象 1. js正则表达式匹配字符之含义      查找以八进制数 规定的字符.     查找以十六进制数 规定 ...

  9. JavaScript -- 时光流逝(八):js中的事件Event的使用

    JavaScript -- 知识点回顾篇(八):js中的事件Event的使用 事件通常与函数配合使用,这样就可以通过发生的事件来驱动函数执行. (1) onabort : onabort 事件会在图像 ...

随机推荐

  1. 使用纯 CSS 实现超酷炫的粘性气泡效果

    最近,在 CodePen 上看到这样一个非常有意思的效果: 这个效果的核心难点在于气泡的一种特殊融合效果. 其源代码在:CodePen Demo -- Goey footer,作者主要使用的是 SVG ...

  2. Unbuntu VS Code启动时闪退暂时的解决方法

    背景: 刚刚试着更新了操作系统,没更新成功,在下载系统更新的时候brave浏览器消失了,wps消失了,搜狗拼音输入法消失了.更新时,卡在Kernal Offset上,然后长按电源键再重启就好了.但是v ...

  3. ModuleNotFoundError: No module named 'distutils.spawn'

    解决办法: 安装python3-distutils sudo apt-get install python3-distutils

  4. Qucs初步使用指南(不是multism)

    众所周知,Multism是一款强大的电路仿真软件,学习电子电路的同学都会接触到. 但是,这软件不支持Linux.(这就很魂淡了啊) 我的主力机是Linux,不能进行电路仿真成了学习的最大障碍. 使用w ...

  5. C#委托的最简单入门和理解

      委托是.net语言中非常重要的一个概念,初学不太好理解也没有关系的,在一次一次的攻关后会领会到委托的精妙,可以说 .net 没有委托就没有后面更高级的事件,异步多线程等等特性的形成可能.所以一定要 ...

  6. WPF 截图控件之文字(七)「仿微信」

    前言 接着上周写的截图控件继续更新添加 文字. 1.WPF实现截屏「仿微信」 2.WPF 实现截屏控件之移动(二)「仿微信」 3.WPF 截图控件之伸缩(三) 「仿微信」 4.WPF 截图控件之绘制方 ...

  7. odoo 14 一些常见问题集

    1 # 当你往tree或者form视图中增加action的时候 2 # 记住!千万别重名 3 # 一旦重名,Export.Delete.Archive.Unarchive都会消失不见 4 # tree ...

  8. SQL及常见的三种类型注释

    SQL(Structure Query Language)语言是数据库的核心语言. SQL的发展是从1974年开始的,其发展过程如下:1974年-----由Boyce和Chamberlin提出,当时称 ...

  9. JavaScript 权威指南-学习笔记(一)

    本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! ## JavaScript 权威指南-学 ...

  10. [护网杯 2018]easy_tornado-1|SSTI注入

    1.打开之后给出了三个连接,分别查看下三个连接内得信息,结果如下: 2.url中参数包含一个文件名与一串应该是md5得加密的字符串,文件名已经获得了,就需要获取加密得字符串,但是加密字符串时需要使用到 ...