Linux Perf: как интерпретировать и находить горячие точки - PullRequest
43 голосов
/ 11 августа 2011

Сегодня я опробовал утилиту linux ' perf , и мне сложно интерпретировать ее результаты. Я привык к callgrind от Valgrind, который, конечно, является совершенно другим подходом к методу перфектов на основе выборки.

Что я сделал:

perf record -g -p $(pidof someapp)
perf report -g -n

Теперь я вижу что-то вроде этого:

+     16.92%  kdevelop  libsqlite3.so.0.8.6               [.] 0x3fe57                                                                                                              ↑
+     10.61%  kdevelop  libQtGui.so.4.7.3                 [.] 0x81e344                                                                                                             ▮
+      7.09%  kdevelop  libc-2.14.so                      [.] 0x85804                                                                                                              ▒
+      4.96%  kdevelop  libQtGui.so.4.7.3                 [.] 0x265b69                                                                                                             ▒
+      3.50%  kdevelop  libQtCore.so.4.7.3                [.] 0x18608d                                                                                                             ▒
+      2.68%  kdevelop  libc-2.14.so                      [.] memcpy                                                                                                               ▒
+      1.15%  kdevelop  [kernel.kallsyms]                 [k] copy_user_generic_string                                                                                             ▒
+      0.90%  kdevelop  libQtGui.so.4.7.3                 [.] QTransform::translate(double, double)                                                                                ▒
+      0.88%  kdevelop  libc-2.14.so                      [.] __libc_malloc                                                                                                        ▒
+      0.85%  kdevelop  libc-2.14.so                      [.] memcpy 
...

Хорошо, эти функции могут быть медленными, но как мне узнать, откуда они вызываются? Поскольку все эти горячие точки лежат во внешних библиотеках, я не вижу способа оптимизировать мой код.

По сути, я ищу какой-то коллограф, аннотированный с накопленной стоимостью, где мои функции имеют более высокую стоимость выборки, чем те библиотечные функции, которые я вызываю.

Возможно ли это с перфом? Если так - как?

Примечание: я обнаружил, что "E" разворачивает callgraph и дает несколько больше информации. Но вызов-граф часто не достаточно глубок и / или завершается случайным образом, не давая информации о том, сколько информации было потрачено где. Пример:

-     10.26%  kate  libkatepartinterfaces.so.4.6.0  [.] Kate::TextLoader::readLine(int&...
     Kate::TextLoader::readLine(int&, int&)                                            
     Kate::TextBuffer::load(QString const&, bool&, bool&)                              
     KateBuffer::openFile(QString const&)                                              
     KateDocument::openFile()                                                          
     0x7fe37a81121c

Может ли быть проблема, что я работаю на 64-битной? См. Также: http://lists.fedoraproject.org/pipermail/devel/2010-November/144952.html (я не использую fedora, но, похоже, он применим ко всем 64-битным системам).

Ответы [ 5 ]

39 голосов
/ 18 декабря 2012

В Linux 3.7 perf наконец-то может использовать информацию DWARF для генерации графа вызовов:

perf record --call-graph dwarf -- yourapp
perf report -g graph --no-children

Отлично, но графический интерфейс curses ужасен по сравнению с VTune, KCacheGrind или подобным ... Рекомендую попробоватьвместо FlameGraphs, что является довольно аккуратной визуализацией: http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html

Примечание. На шаге отчета -g graph делает вывод результатов простым для понимания «относительно общего» процента, а не «относительно родителя».номера.--no-children будет показывать только собственную стоимость, а не инклюзивную стоимость - функция, которую я также считаю бесценной.

Если у вас есть новый perf и процессор Intel, также попробуйте разматыватель LBR, который имеет гораздо лучшую производительностьи создает гораздо меньшие файлы результатов:

perf record --call-graph lbr -- yourapp

Недостатком здесь является то, что глубина стека вызовов более ограничена по сравнению с конфигурацией разматывания DWARF по умолчанию.

18 голосов
/ 22 ноября 2012

Хорошо, эти функции могут быть медленными, но как мне узнать, откуда они вызываются?Поскольку все эти горячие точки лежат во внешних библиотеках, я не вижу способа оптимизировать мой код.

Вы уверены, что ваше приложение someapp построено с опцией gcc -fno-omit-frame-pointer (и, возможно, ее зависимыми библиотеками)?Как то так:

g++ -m64 -fno-omit-frame-pointer -g main.cpp
15 голосов
/ 07 июля 2017

Вы должны попробовать горячую точку: https://www.kdab.com/hotspot-gui-linux-perf-profiler/

Она доступна на github: https://github.com/KDAB/hotspot

Например, она может генерировать пламенные диаграммы для вас.flamegraph

11 голосов
/ 18 октября 2013

Вы можете получить очень подробный отчет на уровне источника с помощью perf annotate, см. Анализ на уровне источника с помощью perf annotate .Это будет выглядеть примерно так (бесстыдно украдено с сайта):

------------------------------------------------
 Percent |   Source code & Disassembly of noploop
------------------------------------------------
         :
         :
         :
         :   Disassembly of section .text:
         :
         :   08048484 <main>:
         :   #include <string.h>
         :   #include <unistd.h>
         :   #include <sys/time.h>
         :
         :   int main(int argc, char **argv)
         :   {
    0.00 :    8048484:       55                      push   %ebp
    0.00 :    8048485:       89 e5                   mov    %esp,%ebp
[...]
    0.00 :    8048530:       eb 0b                   jmp    804853d <main+0xb9>
         :                           count++;
   14.22 :    8048532:       8b 44 24 2c             mov    0x2c(%esp),%eax
    0.00 :    8048536:       83 c0 01                add    $0x1,%eax
   14.78 :    8048539:       89 44 24 2c             mov    %eax,0x2c(%esp)
         :           memcpy(&tv_end, &tv_now, sizeof(tv_now));
         :           tv_end.tv_sec += strtol(argv[1], NULL, 10);
         :           while (tv_now.tv_sec < tv_end.tv_sec ||
         :                  tv_now.tv_usec < tv_end.tv_usec) {
         :                   count = 0;
         :                   while (count < 100000000UL)
   14.78 :    804853d:       8b 44 24 2c             mov    0x2c(%esp),%eax
   56.23 :    8048541:       3d ff e0 f5 05          cmp    $0x5f5e0ff,%eax
    0.00 :    8048546:       76 ea                   jbe    8048532 <main+0xae>
[...]

Не забудьте передать флаги -fno-omit-frame-pointer и -ggdb при компиляции кода.

5 голосов
/ 12 августа 2011

Если ваша программа не имеет очень мало функций и едва ли когда-либо вызывает системную функцию или ввод / вывод, профилировщики, которые производят выборку счетчика программы, мало что скажут вам, как вы обнаруживаете.На самом деле, известный профилировщик gprof был создан специально для того, чтобы попытаться решить проблему бесполезности профилирования, основанного только на времени (но не на том, что это удалось).выборки стека вызовов (таким образом выясняя, откуда поступают вызовы), по настенным часам времени (таким образом включая время ввода-вывода) и сообщая по линии илипо инструкции (тем самым точно определяя вызовы функций, которые вы должны исследовать, а не только те функции, в которых они живут).

Более того, статистика, которую вы должны искать, составляет процент времени в стеке , не количество звонков, не среднее время включения функции. Особенно не "время сам". Если инструкция вызова (или инструкция без вызова) находится в стеке 38% времени, то если бы вы могли от нее избавиться, сколько бы вы сэкономили? 38%! Довольно просто, не так ли?

Примером такого профилировщика является Увеличение .

Есть еще больше вопросов

добавил: @caf заставил меня охотиться за информацией perf, и, поскольку вы включили аргумент командной строки -g, он собирает образцы стеков.Затем вы можете получить отчет call-tree .Затем, если вы убедитесь, что вы производите выборку по времени настенных часов (чтобы у вас было время ожидания, а также время процессора), то вы получите почти то, что вам нужно.

...