GC 和 CC 日志

垃圾回收器 (GC) 和循环收集器 (CC) 日志提供了有关为什么各种 JS 和 C++ 对象在堆中保持存活的信息。垃圾回收器日志和循环收集器日志可以通过多种方式进行分析。特别是,CC 日志可用于理解为什么循环收集器会使某个对象保持存活。这些日志可以手动或自动生成,并且可以在调试和非调试构建中生成。

这会将 Javascript 堆的内容记录到名为 gc-edges-NNNN.log 的文件中。它还会创建一个名为 cc-edges-NNNN.log 的文件,并将堆中循环收集器可见的部分转储到该文件中,其中包括参与循环收集的原生 C++ 对象,以及由这些 C++ 对象保持存活的 JS 对象。

生成日志

在 Firefox 内部

要手动生成 GC 和 CC 日志,请导航到 about:memory 并使用“保存 GC 和 CC 日志”下的按钮。“保存简洁”将生成一个较小的 CC 日志,“保存详细”将提供一个更详细的 CC 日志。(GC 日志在这两种情况下大小相同。)

在多进程 Firefox 中,由于沙箱的原因,您无法记录内容进程的日志。您需要通过在运行 Firefox 时设置 MOZ_DISABLE_CONTENT_SANDBOX=t 来禁用沙箱。

从命令行

简而言之:如果您只想在我们的自动化测试中调试发生的泄漏时获得关闭 GC/CC 日志,则可能需要类似以下内容

MOZ_DISABLE_CONTENT_SANDBOX=t MOZ_CC_LOG_DIRECTORY=/full/path/to/log/directory/ MOZ_CC_LOG_SHUTDOWN=1 MOZ_CC_ALL_TRACES=shutdown ./mach ...

如上一节所述,在多进程 Firefox 中,由于沙箱的原因,您无法记录内容进程的日志。您需要通过在运行 Firefox 时设置 MOZ_DISABLE_CONTENT_SANDBOX=t 来禁用沙箱。

在桌面版 Firefox 上,您可以通过设置 MOZ_CC_LOG_DIRECTORY 环境变量来覆盖日志文件的默认位置。默认情况下,它们会转到一个临时目录,该目录因操作系统而异 - 在 Linux/BSD 上为 /tmp/,在 Windows 上为 $LOCALAPPDATA\Temp\,在 Mac 上为 /var/folders/ 中的某个位置(目录服务为 TmpD/NS_OS_TEMP_DIR 返回的任何目录)。请注意,仅 MOZ_CC_LOG_DIRECTORY=. 不会起作用 - 您需要指定完整路径。在 Android 版 Firefox 上,您可以使用 cc-dump.xpi 扩展将文件保存到 /sdcard。默认情况下,文件是在某个临时目录中创建的,文件路径会打印到错误控制台。

要记录每次循环收集,请设置 MOZ_CC_LOG_ALL 环境变量。要仅记录关闭时的收集,请设置 MOZ_CC_LOG_SHUTDOWN。要使所有 CC 都详细,请将 MOZ_CC_ALL_TRACES 设置为 "all”,或设置为“shutdown”以使仅关闭时的 CC 详细。

可以使用首选项 javascript.options.mem.log 启用实时 GC 日志记录。可以使用 MOZ_GCTIMER 环境变量控制输出到文件。有关值的详细信息,请参阅 统计 API 页面。

将环境变量 MOZ_CC_LOG_THREAD 设置为 main 以仅记录主线程 CC,或设置为 worker 以仅记录工作线程 CC。默认值为 all,它将记录所有 CC。

要在 Try 服务器上获取循环收集器日志,请将 MOZ_CC_LOG_DIRECTORY 设置为 MOZ_UPLOAD_DIR,然后适当地设置其他变量以生成 CC 日志。设置环境变量的方式取决于测试工具,或者您可以修改 nsCycleCollector 中的代码以直接设置它。要找到 Try 运行完成后 CC 日志,请单击特定作业,然后在 TreeHerder 底部窗格中单击“作业详细信息”,您应该会看到下载链接。

要设置环境变量,请在您感兴趣的测试套件的 Python 文件中找到 buildBrowserEnv 方法,并向该文件添加类似以下代码的内容

browserEnv["MOZ_CC_LOG_DIRECTORY"] = os.environ["MOZ_UPLOAD_DIR"]
browserEnv["MOZ_CC_LOG_SHUTDOWN"] = "1"

分析 GC 和 CC 日志

有许多脚本可以在 GitHub 上分析 GC 和 CC 日志

要找出为什么某个对象保持存活,您应该使用 github 存储库根目录中的 find_roots.py。在 CC 日志上使用特定对象或对象类型调用 find_roots.py 将生成从根对象到指定对象的路径。大多数大型泄漏都包含一个 nsGlobalWindow,因此如果您没有更好的想法,这是一个值得尝试的类。

要修复泄漏,下一步是弄清楚为什么根对象保持存活。对于 C++ 对象,您需要找出缺少的引用来自哪里。对于 JS 对象,您需要找出为什么 JS 对象可以从 JS 根访问。对于后者,您可以在 GC 日志上使用相应的 find_roots.py 用于 JS

替代方案

有两个附加组件可用于创建和分析 CC 图。

  • about:cc 简单、丑陋,但功能强大。