查找内存泄漏是一项非常困难的任务,尤其是在涉及使用许多第三方库的现代 JS 代码时。
例如,我目前在 rollup 中面临内存泄漏,涉及 babel 和自定义 babel 插件。
我正在探索几种常见的策略来追捕它们:
- 了解您的运行时及其内存取消分配方案,并遵循有关该方案的最佳实践。
- 本文声称所有现代 JS 运行时实现都使用标记和清除垃圾收集器。它的主要优势之一是它可以正确处理循环引用。(这篇文章还链接了这篇非常过时的研讨会论文。不要太在意它,因为它都是关于循环引用的,这应该不再是问题了。)
- 这篇文章深入探讨了 V8 内存管理(注意:Node 和 Chrome 都基于 V8)。
- 如果您发现内存或 GC 使用量超出您的预期,请分析您的堆内存配置文件以找出内存分配的位置。
- 这个 SO answer解释了如何在 Chrome 中做到这一点,但它的链接已经过时了。这是指向相关 Chrome 文档的直接链接(截至 2021 年)。
- 对于Node,我发现了很多过时的信息。目前,分析堆内存配置文件的最简单方法似乎是使用实验性的--heap-prof命令行参数(例如
node --heap-prof node_modules/rollup/dist/bin/rollup -c分析汇总构建)。然后在 Chrome Dev Tools 中打开它,通过Memory-> Load。
- 分析后,我们可以了解大部分内存是在哪里/如何分配的;但一个关键问题尚未得到解答:
- 既然你知道谁是罪魁祸首(记忆猪),你怎么能找出他们为什么/在哪里仍然挥之不去?而且,更重要的是:内存占用对象的 GC 根(堆栈指针)是什么?
最后一个问题也是我在这里的问题:我们如何分析 Node(或一般的 V8)中的对象分配树?我怎样才能找出我在步骤 (2) 中识别的对象在哪里踢?
通常,这个问题的答案会告诉我们在哪里更改代码以阻止泄漏。(当然,如果您的问题是内存流失,而不是内存泄漏,那么这个问题可能不是那么重要。)
在我的例子中,我知道内存被 Babel …