记一次使用 Chrome DevTools 调试并定位 Electron 子进程内存泄漏的经历

769 阅读4分钟

记一次使用 Chrome DevTools 调试并定位 Electron 子进程内存泄漏的经历

在 Electron 应用开发过程中,我们经常需要使用 child_process.fork() 来创建子进程来处理密集型任务。

当子进程出现性能问题或内存泄漏时,如何进行有效的调试就成为一个关键问题。

业务上出现了在某个操作后,内存占用会一直涨的问题,本文将介绍如何使用 Chrome DevTools 来调试 Electron 子进程,来发现内存泄漏问题。

配置子进程调试环境

在开始调试之前,我们首先需要在创建子进程时开启调试模式,如果未开启调试模式,则无法在 inspect 中发现该进程。

这可以通过在 fork() 方法中设置 execArgv 参数来实现。以下是一个基本的配置示例:

const { fork } = require('child_process');

const childProcess = fork('worker.js', {
  execArgv: ['--inspect=5959']  // 指定调试端口为5959
});

在实际开发中,建议为每个子进程指定不同的调试端口,这样可以避免多个进程之间的端口冲突。选择端口时要注意避免使用系统常用端口,建议使用较高的端口号范围。

连接 Chrome DevTools

启动配置好的子进程后,我们需要连接 Chrome DevTools 进行调试。首先打开 Chrome 浏览器,在地址栏中输入 chrome://inspect

在打开的页面中,你需要点击 "Configure..." 按钮来添加调试配置。

在配置对话框中添加你的本地调试地址,包括主机名(localhost)和端口号(在本例中是5959)。

完成配置后,你会在 "Remote Target" 区域看到可调试的 Node.js 进程。点击对应进程旁边的 "inspect" 链接即可打开 DevTools 调试窗口。

PixPin_2024-12-30_19-27-19.png

使用 Memory 工具分析内存

Memory 工具对于发现内存泄漏和过度内存使用问题非常有效。

在 Memory 面板中,你可以获取堆内存快照来分析内存使用情况。

要进行内存分析,首先在 Memory 面板中选择 "Heap Snapshot" 类型,然后点击 "Take snapshot" 按钮获取当前的堆内存快照。

获取快照前可以点击面板下的垃圾回收按钮,手动触发一次 GC,方便后续 debug。

PixPin_2024-12-30_19-44-58.png

可以看到,获取的内存快照中当前内存占用的值:

PixPin_2024-12-30_19-51-12.png

在业务端执行某些操作后,再获取一次内存快照:

image.png

前后对比可以看到内存明显上升,这里可以使用 memory 的快照对比,来查看前后是哪个部分出现了

这里还可以在搜索栏中输入 Detached 来过滤游离节点列表,但这里场景上是 node 没有 document 之类的元素,所以暂不使用该方法。

image.png

可以通过 Comparison 对两个快照进行对比,查看多出了哪些内存占用,Comparison列表中主要看 New、Deleted、Delta 三项

New 表示此次快照新增的内存占用数量

Deleted 表示此次快照销毁的内存占用数量

Delta 表示用来对比的快照增加或减少的内存占用数量

图上显示,第一个项目的 string 的 Size Delta 显示 +2850396,大概率是 string 的生成逻辑中存在内存泄漏

这个时候就可以点开该对象,查看变量的调用链路

image.png

调用链路可以查看变量或对象的具体调用链路

但实际上,string tab 展开后并不能直接定位到是哪块代码逻辑导致

这里就可以从其他变量入手,再次比对后,可以定位到 string 是由一个 wasm 模块生成,每次的快照都存在一个 ArrayBuffer 变量的内存占用上升

image.png

image.png

每次经过业务交互后,ArrayBuffer 没有被清空,仍存在于全局引用中,可以判定这里就是引起内存泄漏的地方了

从 ArrayBuffer 往下 debug,可以发现这里涉及到第三方库的调用,链路可以从图上获取到,主要在三方库的 withMappingCallback 函数中

这里其实去三方库内部梳理一下,就能发现确实存在一个 wasm 创建的 arraybuffer 对象没有被清空的问题,稍作处理即可

结论

Chrome DevTools 和 Memory 工具为 Electron 子进程的调试提供了强大的支持。通过熟练运用这些工具,我们可以更好地理解和优化应用的性能表现。这些工具提供的详细信息能够帮助我们快速定位和解决问题,从而提升应用的整体性能和稳定性。持续的监控和优化是保持应用健康运行的关键,而掌握这些调试工具和技巧将使这个过程变得更加高效。