【问题标题】:Perf Stat vs Perf Record性能统计与性能记录
【发布时间】:2018-08-19 09:00:11
【问题描述】:

我对 perf recordperf stat 在计算页面错误、缓存未命中和来自 perf list 的任何其他事件等事件时的区别感到困惑。我在“问题 1”的答案下面有 2 个问题可能也有助于回答“问题 2”,但如果没有,我会明确写出来。

问题 1: 据我了解,perf stat 获取计数的“摘要”,但是当与 -I 选项一起使用时,以指定的毫秒间隔获取计数。使用此选项,它是对区间内的计数求和还是在区间内获得平均值,或者完全是其他什么?我想总结一下。 perf wiki 声明它是聚合的,但我想这可能意味着。

问题 2: 为什么perf stat -e <event1> -I 1000 sleep 5 给出的计数不与我对以下命令perf record -e <event1> -F 1000 sleep 5 每秒的计数相加一样?

例如,如果我使用“page-faults”作为 event1 的事件,我会在每个命令下得到以下输出。 (我假设 period 字段是 perf record 的 perf.data 文件中事件的计数)

性能统计

    perf stat -e page-faults -I 1000 sleep 5
    #           time             counts unit events
         1.000252928                 54      page-faults                                                 
         2.000498389      <not counted>      page-faults                                                 
         3.000569957      <not counted>      page-faults                                                 
         4.000659987      <not counted>      page-faults                                                 
         5.000837864                  2      page-faults

完美记录

    perf record -e page-faults -F 1000 sleep 5
    [ perf record: Woken up 1 times to write data ]
    [ perf record: Captured and wrote 0.016 MB perf.data (6 samples) ]
    perf script -F period
             1
             1
             1
             5
            38
           164

我预计如果我将 perf stat 的计数相加,我会得到与 perf record 的总和相同的结果。如果我将 -c 选项与 perf record 一起使用并给出 1 的参数,我确实得到了一个接近的匹配。这仅仅是因为页面错误数量相对较少而导致的巧合吗?

到目前为止我使用过的参考资料:

  • brendangregg's perf blog
  • this page 上的性能记录和统计链接上面提到的“性能维基”
  • 我在here 周围进行了挖掘,以了解 perf 记录实际记录的方式和时间与写入 perf.data 的时间。

提前感谢您提供的任何和所有见解。

【问题讨论】:

  • 聚合意味着总结。对于以稳定速率发生的任何事情(如 cycles),perf stat 的较长 -I 间隔将提供更多计数。

标签: perf


【解决方案1】:

首先,您使用sleeppage-faults 的测试用例并不是一个理想的测试用例。在睡眠期间应该没有页面错误事件,你不能期待任何有趣的事情。为了更容易推理,我建议使用ref-cycles(硬件)事件和繁忙的工作负载,例如awk 'BEGIN { while(1){} }'

问题 1:据我了解 perf stat 得到了 计数,但当与 -I 选项一起使用时,计数在 指定的毫秒间隔。有了这个选项,它总结了 在区间内计数或获取区间内的平均值,或 完全不同的东西?我认为这是总结。

是的。这些值只是总结出来的。您可以通过测试来确认:

$ perf stat -e ref-cycles -I 1000 timeout 10s awk 'BEGIN { while(1){} }'
#           time             counts unit events
 1.000105072      2,563,666,664      ref-cycles                                                  
 2.000267991      2,577,462,550      ref-cycles                                                  
 3.000415395      2,577,211,936      ref-cycles                                                  
 4.000543311      2,577,240,458      ref-cycles                                                  
 5.000702131      2,577,525,002      ref-cycles                                                  
 6.000857663      2,577,156,088      ref-cycles                                                  

[ ... snip ... ]
[ Note that it may not be as nicely consistent on all systems due dynamic frequency scaling ]

$ perf stat -e ref-cycles -I 3000 timeout 10s awk 'BEGIN { while(1){} }' 
#           time             counts unit events
 3.000107921      7,736,108,718      ref-cycles                                                  
 6.000265186      7,732,065,900      ref-cycles                                                  
 9.000372029      7,728,302,192      ref-cycles     

问题2:perf stat -e &lt;event1&gt; -I 1000 sleep 5为什么不给 大约与我对每一秒的计数相加的计数相同 对于以下命令perf record -e &lt;event1&gt; -F 1000 sleep 5?

perf stat -I毫秒 为单位,而 perf record -FHZ (1/s) 为单位,因此 perf stat -I 1000 的对应命令为 perf record -F 1。事实上,随着我们更稳定的事件/工作负载,这看起来更好:

$ perf stat -e ref-cycles -I 1000 timeout 10s awk 'BEGIN { while(1){} }'
#           time             counts unit events
 1.000089518      2,578,694,534      ref-cycles                                                  
 2.000203872      2,579,866,250      ref-cycles                                                  
 3.000294300      2,579,857,852      ref-cycles                                                  
 4.000390273      2,579,964,842      ref-cycles                                                  
 5.000488375      2,577,955,536      ref-cycles                                                  
 6.000587028      2,577,176,316      ref-cycles                                                  
 7.000688250      2,577,334,786      ref-cycles                                                  
 8.000785388      2,577,581,500      ref-cycles                                                  
 9.000876466      2,577,511,326      ref-cycles                                                  
10.000977965      2,577,344,692      ref-cycles                                                  
10.001195845            466,674      ref-cycles    

$ perf record -e ref-cycles -F 1 timeout 10s awk 'BEGIN { while(1){} }'
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.008 MB perf.data (17 samples) ]

$ perf script -F time,period        
3369070.273722:          1 
3369070.273755:          1 
3369070.273911:       3757 
3369070.273916:    3015133 
3369070.274486:          1 
3369070.274556:          1 
3369070.274657:       1778 
3369070.274662:    2196921 
3369070.275523: 47192985748 
3369072.663696: 2578692405 
3369073.663547: 2579122382 
3369074.663609: 2580015300 
3369075.664085: 2579873741 
3369076.664433: 2578638211 
3369077.664379: 2578378119 
3369078.664175: 2578166440 
3369079.663896: 2579238122 

所以你看,最终结果对于perf record -F 也是稳定的。不幸的是,perf record 的文档很差。您可以通过查看底层系统调用man perf_event_open 的文档来了解设置-c-F 的含义:

sample_period, sample_freq “采样”事件是 每 N 个事件生成一个溢出通知,其中 N 由下式给出 sample_period。采样事件的sample_period > 0。当 发生溢出,请求的数据被记录在 mmap 缓冲区中。 sample_type 字段控制每个记录的数据 溢出。

sample_freq 如果您希望使用频率而不是 时期。在这种情况下,您设置了 freq 标志。 内核将 调整采样周期以尝试达到所需的速率。 调整率是一个计时器滴答声。

因此,虽然perf stat 使用内部计时器每隔-i 毫秒读取一次计数器的值,但perf record 会设置一个事件溢出计数器,以便每隔-c 事件进行一次采样。这意味着它会在每个 N 事件(例如每个 N page-faultcycles)中采样一次。使用-F,它会尝试调节此溢出值以达到所需的频率。它尝试不同的值并相应地向上/向下调整。这最终适用于具有稳定速率的计数器,但对于动态事件会得到不稳定的结果。

【讨论】:

  • cat /dev/urandom 是不寻常的,因为它几乎将所有的 CPU 时间都花在了系统调用中。 (这对于测试perf 是否仅测量用户空间很有用,例如cycles:ucycles)。 awk 'BEGIN { while(1){} }' 是用户空间的无限循环。
  • @Zulan 谢谢你的回答。我确实知道 -F 的单位是赫兹,我应该澄清这一点。我想知道为什么如果我在 1 秒内将所有记录样本加起来,它们不会加起来 stat -I 1000 在同一秒内给出的数字。我从您的回答中假设这是因为我的测试用例很差。如果是这种情况,那么为什么perf record 在睡眠操作期间记录任何页面错误。我也许可以看看我是否做了 -a 选项,但我没有,所以有什么?
  • perf record 不应报告任何期间睡眠的事件,但在开始和结束时都有工作。另见*.com/questions/48809347/…
  • @PeterCordes 好点。它包括我的示例的内核,可能是由于perf_event_paranoid=-1