Perf позволяет разбирать callgraph

Как я могу включить C ++ demangling для Perf Callgraph? Кажется, что я делаю символы, когда я вхожу в режим аннотирования, но не в основной callgraph.

Пример кода (используя 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();

команда построения:

clang++ main.cpp -o main -fno-omit-frame-pointer -O0 -lpthread -lbenchmark

команды perf:

perf record -g ./main
perf report -g 'graph,0.5,caller'

Я также попытался включить опцию —demangle, но это не влияет на вывод.

в каллографе пропущены расколотые символы:

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

аннотированная разборка, показывающая расколотые вызовы:

       │
│    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

Системная информация:

  • Ubuntu 15.04 64-bit
  • Intel i5-6600k
  • перф 3.19.8-ckt6
  • лязг 3.6.0-2ubuntu1

11

Решение

У меня была такая же проблема на 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

Также должен быть какой-то способ создать новый пакет linux-tools-common, чтобы действительно интегрировать его в вашу систему. Сейчас, чтобы переопределить официальный перфект новым, просто установите свой PATH:

export PATH=~/install/linux-`uname -r | sed 's/-.*//'`/tools/perf:$PATH
25

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]