"iterations" 在 "perf report -b --branch-history" 中是什么意思(perf record -b -g)

what does "iterations" mean in "perf report -b --branch-history" (of perf record -b -g)

我正在使用 perf 分析一个玩具程序(选择排序),我想知道 iterations 在 perf 报告输出中对应什么。它显示的地址对应于内部循环和 if 语句。我希望有人能帮忙。此外,当我将“-b --branch-history”与 perf 一起使用时,基本块循环列消失了。不知道为什么。

这是我的代码被采样的部分(MAX_LENGTH 是 500):

   35 // FROM: https://www.geeksforgeeks.org/selection-sort
   37 void swap(int *xp, int *yp)
   38 {
   39     int temp = *xp;
   40     *xp = *yp;
   41     *yp = temp;
   42 }
   43       
   44 void selection_sort(int arr[])
   45 {
   46     int i, j, min_idx;
   47
   48     // One by one move boundary of unsorted subarray
   49     for (i = 0; i < MAX_LENGTH-1; i++)
   50     {
   51         // Find the minimum element in unsorted array
   52         min_idx = i;
   53         for (j = i+1; j < MAX_LENGTH; j++)
   54           if (arr[j] < arr[min_idx])
   55             min_idx = j;
   56
   57         // Swap the found minimum element with the first element
   58         swap(&arr[min_idx], &arr[i]);
   59     }
   60 }

编译使用(clang 版本 5.0.0):

clang -O0 -g selection_sort.c -o selection_sort_g_O0

下面是我如何调用性能记录:

sudo perf record -e cpu/event=0xc4,umask=0x20,name=br_inst_retired_near_taken,period=1009/pp -b -g ./selection_sort_g_O0

性能报告及其输出:

sudo perf report -b --branch-history --no-children

Samples: 376  of event 'br_inst_retired_near_taken', Event count (approx.): 37603384
  Overhead  Source:Line               Symbol                  Shared Object                                                                                                                                         ▒
+   51.86%  selection_sort_g_O0[862]  [.] 0x0000000000000862  selection_sort_g_O0                                                                                                                                   ▒
-   24.47%  selection_sort_g_O0[86e]  [.] 0x000000000000086e  selection_sort_g_O0                                                                                                                                   ▒
     0x873 (cycles:1)                                                                                                                                                                                               ▒
   - 0x86e (cycles:1)                                                                                                                                                                                               ▒
      - 23.94% 0x86e (cycles:3 iterations:25)                                                                                                                                                                       ▒
           0x862 (cycles:3)                                                                                                                                                                                         ▒
           0x83f (cycles:1)                                                                                                                                                                                         ▒
           0x87c (cycles:1)                                                                                                                                                                                         ▒
           0x873 (cycles:1)                                                                                                                                                                                         ▒
           0x86e (cycles:1)                                                                                                                                                                                         ▒
           0x86e (cycles:3)                                                                                                                                                                                         ▒
           0x862 (cycles:3)                                                                                                                                                                                         ▒
           0x83f (cycles:1)                                                                                                                                                                                         ▒
           0x87c (cycles:1)                                                                                                                                                                                         ▒
           0x873 (cycles:1)                                                                                                                                                                                         ▒
           0x86e (cycles:1)                                                                                                                                                                                         ▒
           0x86e (cycles:3)                                                                                                                                                                                         ▒
           0x862 (cycles:3)                                                                                                                                                                                         ▒
+   22.61%  selection_sort_g_O0[87c]  [.] 0x000000000000087c  selection_sort_g_O0                                                                                                                                   ▒
+    1.06%  selection_sort_g_O0[8a5]  [.] 0x00000000000008a5  selection_sort_g_O0

我使用 objdump 在地址和源文件行之间进行映射:

objdump -Dleg selection_sort_g_O0 > selection_sort_g_O0.s

../selection_sort.c:53
 836:   8b 45 f4                mov    -0xc(%rbp),%eax
 839:   83 c0 01                add    [=16=]x1,%eax
 83c:   89 45 f0                mov    %eax,-0x10(%rbp)
 83f:   81 7d f0 f4 01 00 00    cmpl   [=16=]x1f4,-0x10(%rbp)
 846:   0f 8d 35 00 00 00       jge    881 <selection_sort+0x71>
../selection_sort.c:54
 84c:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 850:   48 63 4d f0             movslq -0x10(%rbp),%rcx
 854:   8b 14 88                mov    (%rax,%rcx,4),%edx
 857:   48 8b 45 f8             mov    -0x8(%rbp),%rax
 85b:   48 63 4d ec             movslq -0x14(%rbp),%rcx
 85f:   3b 14 88                cmp    (%rax,%rcx,4),%edx
 862:   0f 8d 06 00 00 00       jge    86e <selection_sort+0x5e>
../selection_sort.c:55
 868:   8b 45 f0                mov    -0x10(%rbp),%eax
 86b:   89 45 ec                mov    %eax,-0x14(%rbp)
../selection_sort.c:54
 86e:   e9 00 00 00 00          jmpq   873 <selection_sort+0x63>
../selection_sort.c:53
 873:   8b 45 f0                mov    -0x10(%rbp),%eax
 876:   83 c0 01                add    [=16=]x1,%eax
 879:   89 45 f0                mov    %eax,-0x10(%rbp)
 87c:   e9 be ff ff ff          jmpq   83f <selection_sort+0x2f>

当我通过快速浏览 perf 源代码拼凑信息并提交时,对这个答案持保留态度。

perf report --branch-history 尝试根据跟踪中的分支记录构建程序的控制流。这样做时,它还会检测循环。但是,来自 perf record 的信息可能不完整 - 因此环路检测也会出错。

如果你的系统和我的一样(Haswell 桌面,Linux 4.17.6),perf 可能会记录 LBR for each sample taken. If this LBR contains the 16 most recent branches, you would have to decrease the event period to 16 retired branches. Even with convincing the kernel not to throttle recording,我无法取得任何有意义的结果.

不幸的是,我不知道用 perf.

记录完整分支跟踪的方法

我会尝试重申并在 Zulan 的回答之上添加更多信息。

最后的分支记录 (LBR) 允许在可执行文件中找到热执行路径,以直接检查它们以寻找优化机会。在 perf 中,这是通过扩展调用堆栈显示机制并将最后的基本块添加到调用堆栈中来实现的,调用堆栈通常用于显示最常见的函数调用层次结构。

这可以通过在性能记录中使用 调用图 (-g) 和 LBR (-b) 选项--branch-history 来完成 perf report 中的选项,它将最后一个分支信息添加到调用图中。本质上,它为 8-32 个分支提供了发生某些事情的原因的额外上下文。

最近 perf 版本中的 timed LBR 功能报告每个基本块的平均周期数。

什么是迭代?

据我了解,分支历史代码具有循环检测功能。这样我们就可以通过计算removed loops的次数来得到迭代次数。 通过 Linux 内核中的先前 commit 仅在 perf report 输出(以直方图格式显示)中引入了重复循环的删除。

struct iterations 是一个有用的 C 结构,用于显示 perf report.

中的迭代次数

This 是保存迭代次数以显示在 perf report 输出中的位置。正在从 remove_loops 函数内部调用 save_iterations 函数。

在解析 callchain 时删除循环。

您还可以阅读此 commit,它描述了 perf report 如何显示更新的 Linux 内核版本中引入的迭代次数和更改。