在 `perf record` 输出上运行 `perf stat`?

4
使用Linux性能分析工具perf(版本为v4.15.18)时,可以使用命令perf stat $COMMAND来获取有关该命令的简单统计信息。如果运行perf record命令,则会将大量数据保存到perf.data文件中。

我能否对perf record命令的输出进行perf stat操作?这样我就可以查看记录下来的性能数据,并获得一个简单的概览了吗?


相关:似乎 perf stat report 只能使用由 perf stat record 保存的数据,而不能使用普通的 perf record - Peter Cordes
2个回答

3

perf stat使用硬件性能监控单元以计数模式进行计数,而perf record/perf report与perf.data文件一起使用相同的单位进行溢出模式。在这两种模式下,硬件性能计数器都被配置为将控制寄存器转换成某种性能事件(例如CPU周期或执行的指令),并且每次事件都会增加计数器。

在计数模式下,perf stat将在程序启动时将计数器配置为零,并在程序退出时读取最终计数器值(实际上,计数可能分为几个段,得到相同的结果-完整运行的单个值)。

在性能分析模式(采样分析)下,perf record 会将计数器配置为某个负值,例如 -100000 并安装溢出处理程序(实际值将自动调整为某个频率)。每 100000 次事件,计数器将溢出到零并生成中断。 perf_events 中断处理程序将“样本”记录到环形缓冲区中(当前时间、pid、指令指针,在 -g 中可选地包括调用堆栈),然后保存到 perf.data 中。此处理程序还将计数器重置为 -100000。因此,经过足够长时间的运行,将有数千个样本存储在 perf.data 中,可以用于生成程序的统计分析(程序的哪些部分运行得更频繁)。

perf stat 显示什么? 在 x86_64 CPU 的默认模式下:程序的运行时间(任务时钟和经过的时间),3 个软件事件(上下文切换、CPU 迁移、页面故障),4 个硬件计数器:周期、指令、分支、分支未命中:

$ echo '3^123456%3' | perf stat bc
0
 Performance counter stats for 'bc':
        325.604672      task-clock (msec)         #    0.998 CPUs utilized          
                 0      context-switches          #    0.000 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
               181      page-faults               #    0.556 K/sec                  
       828,234,675      cycles                    #    2.544 GHz                    
     1,840,146,399      instructions              #    2.22  insn per cycle         
       348,965,282      branches                  # 1071.745 M/sec                  
        15,385,371      branch-misses             #    4.41% of all branches        
       0.326152702 seconds time elapsed

“perf record”是什么意思?在单个唤醒事件(环形缓冲区溢出)中,它将1246个样本保存到了perf.data中,并使用默认的硬件事件(循环周期)。

$ echo '3^123456%3' | perf record bc
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.049 MB perf.data (1293 samples) ]

使用perf report --header|lessperf scriptperf script -D命令,您可以查看perf.data文件的内容:
$ perf report --header |grep event
# event : name = cycles:uppp, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|PERIOD ...
# Samples: 1K of event 'cycles:uppp'
$ perf script 2>/dev/null |grep cycles|wc -l 
1293

perf.data中有一些时间戳和程序启动和退出的其他事件(perf script -D |egrep exec\|EXIT),但默认的perf.data中没有足够的信息来完全重建perf stat输出。运行时间仅记录为开始和退出的时间戳,以及每个事件采样的时间戳,软件事件未记录,仅使用了单个硬件事件(cycles; 没有指令、分支、分支缺失)。可以对使用的硬件计数器进行近似,但不是精确的(实际周期约为820-825 mln):

$ perf report --header |grep Event
# Event count (approx.): 836622729

通过非默认记录 perf.data ,可以估计更多的事件:

$ echo '3^123456%3' | perf record -e cycles,instructions,branches,branch-misses bc
[ perf record: Captured and wrote 0.238 MB perf.data (5164 samples) ]
$ perf report --header |egrep Event\|Samples
# Samples: 1K of event 'cycles'
# Event count (approx.): 834809036
# Samples: 1K of event 'instructions'
# Event count (approx.): 1834083643
# Samples: 1K of event 'branches'
# Event count (approx.): 347750459
# Samples: 1K of event 'branch-misses'
# Event count (approx.): 15382047

所以,你不能在perf.data文件上运行perf stat, 但是你可以要求perf report打印带有事件计数估算的标题。你还可以尝试从perf script/perf script -D解析时间戳。

1
这个问题不是Can perf-stat results be generated from a perf.data file?的重复吗?我本来想把它关闭,但后来发现你在两个问题上都发布了类似的答案。 - Peter Cordes
除非问题有其他意思,否则我认为这是一个重复的问题。 - Arnabjyoti Kalita
@osgx,能否请您进一步解释一下您所说的“分析模式”和“计数模式”? 基本上,我在Android上使用了基于Linux perf的simpleperf工具。我分别使用“simpleperf stat”和“simpleperf record”运行完全相同的程序,并且持续时间也相同,但是我得到的指令计数差异约为15%。您能解释一下这种奇怪的现象吗? 因为根据您上面的解释,我认为“stat”应该与“record”相同... - Shih-Chan Huang

0

不行。perf record输出是一个数据文件。perf stat需要一个应用程序。 您可以使用perf script运行预先制作的脚本来聚合和汇总跟踪数据。可以使用以下命令列出可能的脚本。
perf script -l
除了有限数量的预制脚本外,您还可以在Python或Perl中定义自定义perf.data处理脚本。
有关详细信息,请参见perf scriptperf script in pythonperf script in perl


1
有没有一个脚本可以像perf stat一样输出,只要给出来自perf record的perf.data?如果您能展示一个这样的脚本,那将是一个非常有用的答案。显然,无论笨拙的措辞如何,这才是问题真正想要的。 - Peter Cordes
perf report --header |egrep Event\|Samplesperf.data 文件进行总事件计数的估计,但它不是很精确,并且仅限于记录在 perf.data 文件中的事件。 - osgx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接