跳至主要内容

memlab 的工作原理

简而言之,memlab 启动一个无头 Chrome 浏览器,与页面交互,拍摄堆快照,并通过解析、比较和分析堆快照来查找内存泄漏。

1. 浏览器交互

例如,如果我们想找到由目标页面 (TP) 上的 Web 应用程序中的某些交互触发的内存泄漏,memlab 将按以下顺序访问该网页

  • 访问不同的页面 - 称之为基线页面 BP 并拍摄一个名为 SBP 的堆快照(基线页面由测试场景中的 url 回调指定)
  • 访问目标页面 TP 或触发目标交互并拍摄另一个堆快照 STP(导航到目标页面或触发目标交互由测试场景中的 action 回调指定)
  • 最后,导航到不同的页面或使用任何页面内交互来触发从目标页面释放本应释放的内存。 在这里我们到达最终状态 (FP),并拍摄最终堆快照 SFP。 例如,在此步骤中,您可以关闭由目标交互打开的小部件,或返回到基线页面。 (最终导航或交互由测试场景中的 back 回调指定)

有了这些堆快照,memlab 就可以找到内存泄漏,如下一节所述。

2. 堆分析

快照解码:memlab 解码 V8(或 Hermes)堆快照并提供 API,允许查询 JavaScript 堆。

泄漏检测:可以按如下方式导出从目标页面泄漏的对象的超集

(STP \ SBP) ∩ SFP

MemLab 首先通过从 STP(目标堆快照)中排除 SBP 的对象(从基线页面分配的对象)来获得 TP(目标交互)中已分配对象的集合。

然后,它与 FP 中的对象(最终页面上剩余的对象)取交集以获取以下对象:

  1. 从目标交互 (TP) 分配
  2. 但当这些对象本应被释放时,仍然存活。

内置的泄漏检测器使用特定于域的启发式方法来进一步细化泄漏对象的列表(例如,分离的 DOM 元素、错误堆栈跟踪等。memlab 还识别 React Fiber 树并检测未挂载的 Fiber 节点)。

3. 内存泄漏的保留器追踪

memlab 从 GC 根生成到泄漏对象的保留器追踪。 有时某些交互可能会触发数千个泄漏对象,显示所有保留器追踪可能会让人不知所措。 memlab 对所有保留器追踪进行聚类,并且每个内存泄漏集群仅显示一个保留器追踪。

在动画中,A 代表 BP(基线页面),B 代表 TP(目标页面),A' 代表 FP(最终页面)。