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

标签 performance optimization performance-testing perf

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

Ubuntu Linux 18.04 上的 perf v4.15.18

最佳答案

perf 是 statistical (sampling) profiler(在其默认的 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

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

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

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

使用-fno-omit-frame-pointer编译的bc计算器:

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

带有 dwarf 调用图的 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

没有调试信息的 bc 在 -g (fp) 模式下由 perf 进行不正确的调用图处理(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

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

关于performance - 查询 `perf.data` 文件以获取符号的总原始执行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62860433/

相关文章:

windows - CreateFileMapping,MapViewOfFile,如何避免占用系统内存

javascript - html5 canvas 变换和缓存渐变、曲线和旋转

testing - 如何从 Robot Framework 中执行 60 天的测试中提取每周报告和日志

firefox - 性能测试: YSlow on Firefox 37

oracle - 如何确保 PL/SQL 程序在编译时启用了优化?

android - 带有 Firebase 性能监控库的 DexArchiveBuilderException,R8 无法脱糖?

performance - Google 电子表格中的 SUMIFS 函数

sql - 优化 LATERAL join 中的慢聚合

c++ - AVX 256 位代码的性能略逊于等效的 128 位 SSSE3 代码

c++ - 构建优化的 Qt4 - "./configure"标志及其含义