查询“perf.data”文件以获取符号的总原始执行时间

Ror*_*ory 2 optimization performance performance-testing perf

perf曾经用perf record ./application. perf report向我展示了有关它的各种事情。如何显示运行应用程序所需的总时间以及运行特定“符号”/功能的总时间?perf 似乎经常显示百分比,但我想要原始时间,并且它想要“包容性”时间,即包括孩子。

Ubuntu Linux 18.04 上的 perf v4.15.18

osg*_*sgx 5

perf 是统计(采样)分析器(在默认perf record模式下),这意味着它在函数进入和退出时没有精确的时间戳(精确数据需要跟踪)。Perf 要求操作系统内核每秒生成数千次中断(如果-e cycles支持的话,硬件 PMU 为 4 kHz,软件事件更少-e cpu-clock)。程序执行的每次中断都被记录为样本,其中包含EIP(当前指令指针)、pid(进程/线程id)、当前时间的时间戳。当程序运行几秒钟时,将会有数千个样本,并且perf report可以根据它们生成直方图:程序代码的哪些部分(哪些函数)比其他部分执行得更频繁。您将大致了解某些函数确实占用了程序执行时间的 30% 左右,而其他函数则占用了 5%。

perf 报告不计算总的程序执行时间(它可以通过比较第一个和最后一个样本的时间戳来估计它,但如果存在关闭 CPU 周期,则它是不准确的)。但它确实估计了事件总数(它打印在交互式 TUI 的第一行中,并在文本输出中列出):

$ perf report |grep approx
# Samples: 1K of event 'cycles'
# Event count (approx.): 844373507
Run Code Online (Sandbox Code Playgroud)

有一个perf report -n选项可以在百分比列旁边添加“样本数”列。

Samples: 1K of event 'cycles', Event count (approx.): 861416907
Overhead       Samples  Command  Shared Object     Symbol
  42.36%           576  bc       bc                [.] _bc_rec_mul
  37.49%           510  bc       bc                [.] _bc_shift_addsub.isra.3
  14.90%           202  bc       bc                [.] _bc_do_sub
   0.89%            12  bc       bc                [.] bc_free_num
Run Code Online (Sandbox Code Playgroud)

但采样的时间间隔不同,并且不如计算的开销精确(每个样本可能具有不同的权重)。我建议您运行perf stat ./application以获得应用程序的实际总运行时间和总硬件计数。当您的应用程序具有稳定的运行时间时会更好(perf stat -r 5 ./application工具估计的变化为最后一列中的“+- 0.28%”)

要包含子函数,必须在每次中断时对堆栈跟踪进行采样。在默认模式下不对它们进行采样perf record-g 使用或选项打开此采样 --call-graph dwarfperf record -g ./applicationperf record --call-graph dwarf ./application。在 Linux 中正确使用它来预装库或应用程序并不简单(因为大多数发行版都会从包中删除调试信息),但可以用于您自己使用调试信息编译的应用程序。默认值与要求所有代码都使用gcc选项编译-g相同,非默认值更可靠。通过正确准备的程序和库、单线程应用程序以及足够长的堆栈大小示例(默认为 8KB,用 更改),应该显示大约 99% 的和函数(包括子函数)。--call-graph fp-fno-omit-frame-pointer--call-graph dwarf--call-graph dwarf,65536perf report_startmain

bc 计算器编译为-fno-omit-frame-pointer

bc-no-omit-frame$ echo '3^123456%3' | perf record -g  bc/bc
bc-no-omit-frame$ perf report
Samples: 1K of event 'cycles:uppp', Event count (approx.): 811063902
  Children      Self  Command  Shared Object       Symbol
+   98.33%     0.00%  bc       [unknown]           [.] 0x771e258d4c544155
+   98.33%     0.00%  bc       libc-2.27.so        [.] __libc_start_main
+   98.33%     0.00%  bc       bc                  [.] main
Run Code Online (Sandbox Code Playgroud)

带有矮调用图的 bc 计算器:

$ echo '3^123456%3' | perf record --call-graph dwarf  bc/bc
$ perf report
Samples: 1K of event 'cycles:uppp', Event count (approx.): 898828479
  Children      Self  Command  Shared Object     Symbol
+   98.42%     0.00%  bc       bc                [.] _start
+   98.42%     0.00%  bc       libc-2.27.so      [.] __libc_start_main
+   98.42%     0.00%  bc       bc                [.] main
Run Code Online (Sandbox Code Playgroud)

没有调试信息的 bc 在 (fp) 模式下 perf 的调用图处理不正确-g(main 没有 99%):

$ cp bc/bc bc.strip
$ strip -d bc.strip
$ echo '3^123456%3' | perf record --call-graph fp ./bc.strip 
Samples: 1K of event 'cycles:uppp', Event count (approx.): 841993392
  Children      Self  Command   Shared Object     Symbol
+   43.94%    43.94%  bc.strip  bc.strip          [.] _bc_rec_mul
+   39.73%    39.73%  bc.strip  bc.strip          [.] _bc_shift_addsub.isra.3
+   11.27%    11.27%  bc.strip  bc.strip          [.] _bc_do_sub
+    0.92%     0.92%  bc.strip  libc-2.27.so      [.] malloc
Run Code Online (Sandbox Code Playgroud)

有时perf report --no-children禁用对 self+children 开销的排序(将按“self”开销排序)很有用,例如,当未完全捕获调用图时。