perf启用callgraph的demangling

hel*_*922 16 c++ linux ubuntu microbenchmark perf

如何为perf调用图启用C++ demangling?当我进入注释模式时,似乎是解码符号,而不是在主调用图中.

示例代码(使用Google Benchmark):

#include <benchmark/benchmark.h>
#include <vector>

static __attribute__ ((noinline)) int my_really_big_function()
{
  for(size_t i = 0; i < 1000; ++i)
  {
    benchmark::DoNotOptimize(i % 5);
  }
  return 0;
}

static __attribute__ ((noinline)) void caller1()
{
  for(size_t i = 0; i < 1000; ++i)
  {
    benchmark::DoNotOptimize(my_really_big_function());
    benchmark::DoNotOptimize(i % 5);
  }
}

static __attribute__ ((noinline)) void myfun(benchmark::State& state)
{
  while(state.KeepRunning())
  {
    caller1();
  }
}

BENCHMARK(myfun);

BENCHMARK_MAIN();
Run Code Online (Sandbox Code Playgroud)

构建命令:

clang++ main.cpp -o main -fno-omit-frame-pointer -O0 -lpthread -lbenchmark
Run Code Online (Sandbox Code Playgroud)

perf命令:

perf record -g ./main
perf report -g 'graph,0.5,caller'
Run Code Online (Sandbox Code Playgroud)

我也试过启用--demangle选项,但这似乎不会影响输出.

callgraph缺少demangled符号:

Samples: 3K of event 'cycles', Event count (approx.): 2946754102
Children      Self  Command  Shared Object      Symbol
+   99.82%     0.00%  main     main               [.] _ZL5myfunRN9benchmark5StateE
+   99.82%     0.00%  main     main               [.] _ZN9benchmark12_GLOBAL__N_111RunInThreadEPKNS_8internal9Benchmark8InstanceEmiPNS0_11ThreadStatsE
+   99.82%     0.00%  main     main               [.] _ZN9benchmark22RunSpecifiedBenchmarksEPNS_17BenchmarkReporterE
+   99.82%     0.00%  main     main               [.] main
+   99.82%     0.00%  main     libc-2.21.so       [.] __libc_start_main
+   99.82%     0.00%  main     [unknown]          [.] 0x7fbe258d4c544155
+   99.75%     0.30%  main     main               [.] _ZL7caller1v
+   99.52%    99.46%  main     main               [.] _ZL22my_really_big_functionv
Run Code Online (Sandbox Code Playgroud)

带注释的反汇编显示解码调用:

       ?
       ?    0000000000404310 <caller1()>:
       ?    _ZL7caller1v():
       ?      push   %rbp
       ?      mov    %rsp,%rbp
       |    $0x30,%rsp
       |   $0x0,-0x18(%rbp)
       ?10:   cmpq   $0x3e8,-0x18(%rbp)
       ?    ? jae    6f
       ?    ? callq  my_really_big_function()
       ?      lea    -0x1c(%rbp),%rcx
       ?      mov    %eax,-0x1c(%rbp)
 14.29 ?      mov    %rcx,-0x10(%rbp)
       ?      mov    -0x10(%rbp),%rcx
       ?      lea    -0x28(%rbp),%rcx
       ?      mov    $0x5,%eax
       ?      mov    %eax,%edx
       ?      mov    -0x18(%rbp),%rax
       ?      xor    %esi,%esi
       ?      mov    %rdx,-0x30(%rbp)
       ?      mov    %esi,%edx
       ?      mov    -0x30(%rbp),%rdi
       ?      div    %rdi
 85.71 ?      mov    %rdx,-0x28(%rbp)
       ?      mov    %rcx,-0x8(%rbp)
       ?      mov    -0x8(%rbp),%rcx
       ?      mov    -0x18(%rbp),%rax
       ?      add    $0x1,%rax
       ?      mov    %rax,-0x18(%rbp)
       ?    ? jmpq   10
       ?6f:   add    $0x30,%rsp
       ?      pop    %rbp
       ?    ? retq
Run Code Online (Sandbox Code Playgroud)

系统信息:

  • Ubuntu 15.04 64位
  • 英特尔i5-6600k
  • perf 3.19.8-ckt6
  • clang 3.6.0-2ubuntu1

Mic*_*pso 32

我在Ubuntu 15.10上遇到了同样的问题,我在这里找到了解决方案:https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1396654

更新:适用于Ubuntu 18.10

以下是步骤:

sudo apt-get install libiberty-dev binutils-dev
mkdir ~/install
cd ~/install
# If the following apt-get doesn't work on your system,
# uncomment deb-src lines in your /etc/apt/sources.list,
# as suggested by @ctitze
# or you can download it manually from packages.ubuntu.com
# as @aleixrocks suggested in the comment below
apt-get source linux-tools-`uname -r`
sudo apt-get build-dep linux-tools-`uname -r`
cd linux-`uname -r | sed 's/-.*//'`/tools/perf
make

# now you should see the new "perf" executable here
./perf
Run Code Online (Sandbox Code Playgroud)

还应该有一些方法来创建一个新的linux-tools-common软件包来真正将它集成到你的系统中.现在要用新的覆盖官方perf,只需设置你的路径:

export PATH=~/install/linux-`uname -r | sed 's/-.*//'`/tools/perf:$PATH
Run Code Online (Sandbox Code Playgroud)

  • 在我的情况下,我无法使用apt-get源下载ubuntu Linux内核源代码,因为找不到包.相反,我从https://packages.ubuntu.com/下载了它.然后,我可以通过直接在下载的包的tools/perf目录中执行make来构建它(在安装libiberty-dev binutils-dev之后,如答案中所述,但没有apt-get build-dep步骤). (2认同)
  • 如果手动下载包会导致太多麻烦,您也可以尝试在`/ etc/apt/sources.list`中启用源PPA.只需取消注释`deb-src`行,保存文件,并使用`sudo apt-get update`更新包缓存.然后`apt-get source`应该起作用(至少它对我有用). (2认同)
  • @cli,要解决16.04上的“'__NR_perf_event_open”未声明的错误,我必须删除/重命名“ linux-4.4.0 / tools / perf / util / include / asm / unistd_64.h”(这是一个空文件,然后编译器可以精简所需的文件)。 (2认同)