V8 的 Linux perf 集成

V8 内置支持 Linux perf 工具。它可以通过 --perf-prof 命令行选项启用。
V8 在执行期间将性能数据写入一个文件,该文件可用于使用 Linux perf 工具分析 V8 的 JIT 代码(包括 JS 函数名称)的性能。

要求 #

构建 V8 #

要使用 V8 与 Linux perf 的集成,您需要使用 enable_profiling = true gn 标志构建它。

echo 'enable_profiling = true' >> out/x64.release/args.gn
autoninja -C out/x64.release

使用 linux-perf-d8.py 分析 d8 #

构建 d8 后,您可以开始使用 linux perf。

tools/profiling/linux-perf-d8.py out/x64.release/d8 path/to/test.js;

更完整的示例

echo '(function f() {
var s = 0; for (var i = 0; i < 1000000000; i++) { s += i; } return s;
})();'
> test.js;

# Use custom V8 flags and a separate output dir for less clutter:
mkdir perf_results
tools/profiling/linux-perf-d8.py --perf-data-dir=perf_results \
out/x64.release/d8 --expose-gc --allow-natives-syntax test.js;

# Fancy UI (`-flame` is googler-only, use `-web` as a public alternative):
pprof -flame perf_results/XXX_perf.data.jitted;
# Terminal-based tool:
perf report -i perf_results/XXX_perf.data.jitted;

查看 linux-perf-d8.py --help 以获取更多详细信息。请注意,您可以在 d8 二进制文件参数之后使用所有 d8 标志。

使用 linux-perf-chrome.py 分析 Chrome 或 content_shell #

  1. 您可以使用 linux-perf-chrome.py 脚本分析 chrome。确保添加 必需的 chrome gn 标志 以获得正确的 C++ 符号。

  2. 构建完成后,您可以使用 C++ 和 JS 代码的完整符号来分析网站。

    mkdir perf_results;
    tools/profiling/linux-perf-chrome.py out/x64.release/chrome \
    --perf-data-dir=perf_results --timeout=30
  3. 导航到您的网站,然后关闭浏览器(或等待 --timeout 完成)。

  4. 退出浏览器后,linux-perf.py 将对文件进行后处理,并显示一个包含每个渲染器进程结果文件的列表。

    chrome_renderer_1583105_3.perf.data.jitted      19.79MiB
    chrome_renderer_1583105_2.perf.data.jitted       8.59MiB
    chrome_renderer_1583105_4.perf.data.jitted       0.18MiB
    chrome_renderer_1583105_1.perf.data.jitted       0.16MiB
    

探索 linux-perf 结果 #

最后,您可以使用 Linux perf 工具来探索 d8 或 chrome 渲染器进程的配置文件。

perf report -i perf_results/XXX_perf.data.jitted

您还可以使用 pprof 生成更多可视化。

# Note: `-flame` is google-only, use `-web` as a public alternative:
pprof -flame perf_results/XXX_perf.data.jitted;

低级 linux-perf 使用 #

直接使用 linux-perf 与 d8 #

根据您的用例,您可能需要直接使用 linux-perf 与 d8
这需要一个两步过程,首先 perf record 创建一个 perf.data 文件,该文件必须使用 perf inject 进行后处理以注入 JS 符号。

perf record --call-graph=fp --clockid=mono --freq=max \
--output=perf.data
out/x64.release/d8 \
--perf-prof --no-write-protect-code-memory \
--interpreted-frames-native-stack \
test.js;
perf inject --jit --input=perf.data --output=perf.data.jitted;
perf report --input=perf.data.jitted;

V8 linux-perf 标志 #

--perf-prof 用于 V8 命令行以记录 JIT 代码中的性能样本。

--nowrite-protect-code-memory 用于禁用代码内存的写保护。这是必要的,因为 perf 在看到与从代码页中删除写位相对应的事件时会丢弃有关代码页的信息。以下是一个从测试 JavaScript 文件中记录样本的示例。

--interpreted-frames-native-stack 用于为解释函数创建不同的入口点(InterpreterEntryTrampoline 的复制版本),以便 perf 可以根据地址单独区分它们。由于 InterpreterEntryTrampoline 必须被复制,因此这会带来轻微的性能和内存回归。

直接使用 linux-perf 与 chrome #

  1. 您可以使用相同的 V8 标志来分析 chrome 本身。按照上述说明使用正确的 V8 标志,并将 必需的 chrome gn 标志 添加到您的 chrome 构建中。

  2. 构建完成后,您可以使用 C++ 和 JS 代码的完整符号来分析网站。

    out/x64.release/chrome \
    --user-data-dir=`mktemp -d` \
    --no-sandbox --incognito --enable-benchmarking \
    --js-flags='--perf-prof --no-write-protect-code-memory --interpreted-frames-native-stack'
  3. 启动 chrome 后,使用任务管理器查找渲染器进程 ID,并使用它来启动分析。

    perf record -g -k mono -p $RENDERER_PID -o perf.data
  4. 导航到您的网站,然后继续下一部分,了解如何评估 perf 输出。

  5. 执行完成后,将从 perf 工具收集的静态信息与 V8 为 JIT 代码输出的性能样本相结合。

    perf inject --jit --input=perf.data --output=perf.data.jitted
  6. 最后,您可以使用 Linux perf 工具进行探索

构建 perf #

如果您有一个过时的 linux 内核,您可以在本地构建具有 jit 支持的 linux-perf。

在以下步骤中,将 perf 称为 some/director/tip/tools/perf/perf