如何正确调试电子内存问题?

Posted

技术标签:

【中文标题】如何正确调试电子内存问题?【英文标题】:How to properly debug Electron memory issues? 【发布时间】:2021-12-17 23:22:27 【问题描述】:

最近,我和我的团队越来越专注于解决 Electron 应用程序中的高内存使用问题。我们的应用程序有几个渲染器进程,随着时间的流逝,最终会消耗大量内存,而我们的应用程序几乎没有使用该内存量。我们很可能需要花费大量时间来追踪此泄漏。

让我对正在发生的事情感到非常困惑的关键是,当在内存选项卡上查看 Chrome Devtools 时,与我们拉出 Activity Monitor 的值相比,该值似乎完全合理。 (以下图片同时拍摄)

我不知道从哪里开始获取这些信息。为什么这些数字如此不同?我们的 Web 应用程序中是否存在仅通过 Electron 应用程序内存暴露自身的泄漏?我们如何设置 Electron 来渲染我们的应用程序有什么问题吗?两者都有吗?

这种类型的问题在使用 Electron 时似乎很常见,但是对于我来说,我找不到资源来开始真正调试这个问题。我不一定要在我的设置上寻找直接答案,因为我没有直接提供足够的信息。我只是在执行一项事实调查任务,以更好地了解如何在 Electron 生态系统中调试此类问题。

【问题讨论】:

【参考方案1】:

我对 Electron 了解不多,但我喜欢研究这类问题!我当然没有为您提供明确的解决方案,但我希望其中一些内容可以帮助您调试或在内存问题上取得一些进展。

要提一提的是,您可能会遇到与 3 个不同的事情有关的内存问题:

可能是您自己的代码导致内存泄漏。 可能是 Electron 导致了内存泄漏。 可能是 Chromium 导致了内存泄漏(因为 Electron 使用的是 Chromium)。

另外要提到的是,它不一定是内存“泄漏”,也可能只是内存膨胀。不同之处在于,如果发生内存泄漏,它会一直泄漏内存,直到它崩溃,而发生内存膨胀时,它只会占用所有内存,直到没有任何剩余,然后才开始从内存中删除旧的东西。

根据您分享的内容,如果不进行调试和找出问题,很难判断问题可能出在哪里。所以我要做的是首先确保不是你自己的代码导致泄漏/膨胀,尝试运行你的代码的一小部分,看看内存是否仍然是一个问题,然后开始逐步添加更多的代码部分,直到你已经添加了一切。如果在任何时候内存开始成为问题,则可能是代码本身(但不一定,那么至少您已经确定了它是什么)。例如,如果您使用的图像组件的内存突然开始增加,您可以确定这与图像/缓存有关。

您可以尝试的潜在方法

首先调试您的代码以确保它不是您的代码,或者如果它是您的代码,至少可以准确指出它是什么。 检查您正在使用的图像(或其他资源)是否正在缓存,以及是否是导致内存堆积的原因。您可以使用缓存控制标头并在开发工具中禁用缓存,以确保开发环境中没有缓存,以便您查看是否是缓存。 检查是否有任何浏览器设置可以在 Electron 中使用,我不知道你是否可以,但如果 Electron 使用 Chromium,那么你应该可以使用诸如硬件加速、禁用等设置它从后台运行和预加载页面优化。我从这里读到的东西:https://ssiddique.info/fix-chrome-memory-leak.html。或者尝试使用您能找到的任何类似设置。

凭直觉,我相信问题在于缓存。在我看来,Electron 可以使用荒谬的内存量,如果它不断地缓存图像而不删除它,它会占用内存直到没有任何东西,然后它才会开始从缓存中删除旧的东西。更糟糕的是,如果您使用交换/虚拟内存并且 RAM 已满,它还会在将其从 RAM 中删除之前将其写入磁盘,这也可以解释磁盘空间的增加。我个人会尝试禁用所有缓存并查看会发生什么。这也是您可以在此处看到的内容:Changing backgroundImage causes memory leak (Electron)。这是另一个例子:Changing image src constantly / memory usage (Electron),在这种情况下,我认为回答这个问题的人可能会看到内存减少,因为当他使用 base64 时,图像不再被缓存。这是 Chromium 的另一个问题:https://forums.raspberrypi.com/viewtopic.php?t=296598,其中清除大量缓存文件也有效。在这里,electron memory usage profiling,是另一个人说他们所做的只是“显示图像”。缓存让我感觉有点刺痛。

您可以尝试/查看的完整无聊列表

https://github.com/electron/electron/issues/21586

在打开和关闭窗口时,Electron 中存在一个未解决的问题,即内存泄漏。

Event Emitter Memory Leak in Electron App

有一个代码本身导致内存泄漏的示例,但它也可能是与 Electron 本身相关的代码。

Memory leak in BrowserWindow, Electron

还有另一个代码可以破坏它的例子,在这种情况下,它也是 Electron 特有的。

chrome and chromium growing memory usage

有一个 chromium 导致内存泄漏的例子,但是我不知道这是否真的是一个问题,因为它从未得到回答。

How to increase the max memory limit for the app built by electron-builder?

您可以尝试使用max-old-space-size 增加/减少内存。

另一个关键考虑因素

我发现的另一个最可行的东西是https://seenaburns.com/debugging-electron-memory-usage/,他最终得出结论,它与 RSS(以及缓存)有关。这个人,https://spectrum.chat/electron/general/debugging-high-memory-usage-in-electron~80057ff2-a51c-427f-b6e1-c297d47baf5b,也提到了它与 RSS 相关,我还在这里发现了一个电子的未解决问题:https://github.com/electron/electron/issues/25208,这与 RSS 内存泄漏有关。

最后说明

Electron 将使用大量内存,因为它在浏览器/桌面 Chromium 中运行完整的浏览器,同时运行 v8 和所有它自己的代码。除此之外,Chromium 还以高内存使用而闻名。所以看到高内存是比较正常的。除此之外,如果内存只是膨胀,通过查明膨胀它的原因来解决这个问题会更容易,这很可能类似于缓存。如果是内存泄漏,那么它可能是任何东西,很可能是您自己的代码,但也可能是 Electron 或 Chromium 中的官方错误。

如果一切都失败了,您可以加入https://www.reddit.com/r/programming/comments/7p7s8q/electron_is_cancer/ 的潮流。根据我的经验,用 Electron 编写的东西非常慢,内存密集,并且无法在浏览器中生存,Discord 和 Slack 是最大的罪魁祸首。我可以在浏览器中打开任何应用程序几天而没有问题,但是离开其中任何一个最终都会使我的浏览器崩溃。 Zoom 稍微好一点,但这可能是因为他们使用自己的 SDK 并且只使用 Electron 作为接口,而 atom 也比大多数应用程序更好,但正如该帖子中的一位*** cmets 所指出的那样,他们重写了一些c++中的核心部分。我对 Electron 了解不多,所以我对此没有可信的意见,但我使用的使用 Electron 构建的应用程序总是存在相同的内存问题。我认为 Electron 是一个很棒的想法和概念,并且随着时间的推移,应用程序已经有了很大的改进,因此请尊重那些致力于它的团队,但我也认为它仍然有很多问题需要解决,尤其是在涉及到记忆。

【讨论】:

以上是关于如何正确调试电子内存问题?的主要内容,如果未能解决你的问题,请参考以下文章

Sqlite3内存调试

如何在 Rust 中调试内存问题?

如何调试内存分配问题?

Linux如何调试内存泄漏

Linux如何调试内存泄漏

调试 - 如何分析反应本机内存使用情况