🌐 Using Linux Perf
Linux Perf 提供针对 JavaScript、本地以及操作系统级别的底层 CPU 分析。
重要:本教程仅适用于 Linux。
🌐 How To
Linux Perf 通常可以通过 linux-tools-common 软件包获得。通过 --perf-basic-prof 或 --perf-basic-prof-only-functions,我们能够启动一个支持 perf_events 的 Node.js 应用。
🌐 Linux Perf is usually available through the linux-tools-common package. Through either --perf-basic-prof or
--perf-basic-prof-only-functions we are able to start a Node.js application supporting perf_events.
--perf-basic-prof 将始终写入文件(/tmp/perf-PID.map),这可能导致磁盘无限增长。如果这是一个问题,可以使用模块:linux-perf 或 --perf-basic-prof-only-functions。
两者之间的主要区别在于,--perf-basic-prof-only-functions 产生的输出较少,它是生产环境分析的可行选项。
🌐 The main difference between both is that --perf-basic-prof-only-functions produces less output, it is a viable option
for production profiling.
# Launch the application an get the PID $ node --perf-basic-prof-only-functions index.js & [1] 3870
然后根据所需频率记录事件:
🌐 Then record events based in the desired frequency:
$ sudo perf record -F 99 -p 3870 -g
在此阶段,你可能希望在应用中使用负载测试,以生成更多记录以进行可靠的分析。作业完成后,通过向命令发送 SIGINT(Ctrl-C)来关闭 perf 进程。
🌐 In this phase, you may want to use a load test in the application in order to generate more records for a reliable analysis. When the job is done, close the perf process by sending a SIGINT (Ctrl-C) to the command.
perf 会在 /tmp 文件夹中生成一个文件,通常名为 /tmp/perf-PID.map(在上例中为 /tmp/perf-3870.map),其中包含每个被调用函数的跟踪信息。
🌐 The perf will generate a file inside the /tmp folder, usually called /tmp/perf-PID.map
(in above example: /tmp/perf-3870.map) containing the traces for each function called.
要将这些结果汇总到特定文件中,请执行:
🌐 To aggregate those results in a specific file execute:
$ sudo perf script > perfs.out
$ cat ./perfs.out node 3870 25147.878454: 1 cycles: ffffffffb5878b06 native_write_msr+0x6 ([kernel.kallsyms]) ffffffffb580d9d5 intel_tfa_pmu_enable_all+0x35 ([kernel.kallsyms]) ffffffffb5807ac8 x86_pmu_enable+0x118 ([kernel.kallsyms]) ffffffffb5a0a93d perf_pmu_enable.part.0+0xd ([kernel.kallsyms]) ffffffffb5a10c06 __perf_event_task_sched_in+0x186 ([kernel.kallsyms]) ffffffffb58d3e1d finish_task_switch+0xfd ([kernel.kallsyms]) ffffffffb62d46fb __sched_text_start+0x2eb ([kernel.kallsyms]) ffffffffb62d4b92 schedule+0x42 ([kernel.kallsyms]) ffffffffb62d87a9 schedule_hrtimeout_range_clock+0xf9 ([kernel.kallsyms]) ffffffffb62d87d3 schedule_hrtimeout_range+0x13 ([kernel.kallsyms]) ffffffffb5b35980 ep_poll+0x400 ([kernel.kallsyms]) ffffffffb5b35a88 do_epoll_wait+0xb8 ([kernel.kallsyms]) ffffffffb5b35abe __x64_sys_epoll_wait+0x1e ([kernel.kallsyms]) ffffffffb58044c7 do_syscall_64+0x57 ([kernel.kallsyms]) ffffffffb640008c entry_SYSCALL_64_after_hwframe+0x44 ([kernel.kallsyms]) ....
原始输出可能有点难以理解,因此通常会使用原始文件来生成火焰图,以便更好地可视化。
🌐 The raw output can be a bit hard to understand so typically the raw file is used to generate flamegraphs for a better visualization.

要从此结果生成火焰图,请从第6步开始按照本教程操作。
🌐 To generate a flamegraph from this result, follow this tutorial from step 6.
因为 perf 输出不是 Node.js 特有的工具,它在 Node.js 中优化 JavaScript 代码的方式可能会存在问题。更多参考请见 perf 输出问题。
🌐 Because perf output is not a Node.js specific tool, it might have issues with how JavaScript code is optimized in
Node.js. See perf output issues for a
further reference.
🌐 Useful Links