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 简单、丑陋,但功能强大。