Запросить у файла `perf.data` общее время необработанного выполнения символа - PullRequest
0 голосов
/ 12 июля 2020

Я использовал perf для создания файла perf с perf record ./application. perf report показывает мне разные вещи об этом. Как я могу показать общее время, необходимое для запуска приложения, и общее время, необходимое для запуска определенного c "символа" / функции? Похоже, что perf часто показывает проценты, но мне нужно необработанное время, и ему нужно "инклюзивное" время, то есть с учетом детей.

perf v4.15.18 на Ubuntu Linux 18.04

1 Ответ

1 голос
/ 13 июля 2020

perf - это статистический (выборочный) профилировщик (в его режиме по умолчанию perf record), и это означает, что он не имеет точных отметок времени при входе и выходе из функции (для точных данных требуется трассировка). Perf просит ядро ​​ОС генерировать прерывания тысячи раз в секунду (4 кГц для аппаратного PMU, если поддерживается -e cycles, меньше для программного события -e cpu-clock). Каждое прерывание выполнения программы записывается как образец, который содержит EIP (текущий указатель инструкции), pid (идентификатор процесса / потока), временную метку текущего времени. Когда программа работает в течение нескольких секунд, будут тысячи выборок, и perf report может генерировать из них гистограммы: какие части программного кода (какие функции) выполнялись чаще, чем другие. Вы получите общий c обзор того, что некоторые функции занимали около 30% времени выполнения программы, а другие - 5%.

отчет perf не вычисляет общее время выполнения программы (он может оценить его, сравнив временные метки первый и последний образцы, но это не точно, если бы были периоды отсутствия процессора). Но он оценивает общее количество событий (оно печатается в первой строке интерактивного интерфейса пользователя и указывается в текстовом выводе):

$ perf report |grep approx
# Samples: 1K of event 'cycles'
# Event count (approx.): 844373507

Существует опция perf report -n, которая добавляет столбец «количество образцов» рядом с столбец процентов.

Samples: 1K of event 'cycles', Event count (approx.): 861416907
Overhead       Samples  Command  Shared Object     Symbol
  42.36%           576  bc       bc                [.] _bc_rec_mul
  37.49%           510  bc       bc                [.] _bc_shift_addsub.isra.3
  14.90%           202  bc       bc                [.] _bc_do_sub
   0.89%            12  bc       bc                [.] bc_free_num

Но выборки берутся с разными интервалами и они менее точны, чем вычисленные накладные расходы (каждая выборка может иметь разный вес). Я рекомендую вам запустить perf stat ./application, чтобы получить реальное общее время работы и общее количество оборудования для вашего приложения. Лучше, когда ваше приложение имеет стабильное время работы (сделайте perf stat -r 5 ./application, чтобы вариация оценивалась инструментом как "+ - 0,28%" в последнем столбце)

Для включения дочерних функций трассировки стека должны отбираться при каждом прерывании . Они не выбираются в режиме по умолчанию perf record. Эта выборка включается с параметрами -g или --call-graph dwarf: perf record -g ./application или perf record --call-graph dwarf ./application. Его непросто правильно использовать для предустановленных библиотек или приложений в Linux (поскольку большинство дистрибутивов удаляют отладочную информацию из пакетов), но его можно использовать для ваших собственных приложений, скомпилированных с отладочной информацией. Значение по умолчанию -g, которое совпадает с --call-graph fp, требует, чтобы весь код был скомпилирован с параметром -fno-omit-frame-pointer g cc, а нестандартный --call-graph dwarf более надежен. С правильно подготовленной программой и библиотеками, однопоточным приложением и достаточно длинными образцами размера стека (по умолчанию 8 КБ, измените на --call-graph dwarf,65536), perf report должно показать около 99% для _start и main функций (включая дочерние ).

b c калькулятор скомпилирован с -fno-omit-frame-pointer:

bc-no-omit-frame$ echo '3^123456%3' | perf record -g  bc/bc
bc-no-omit-frame$ perf report
Samples: 1K of event 'cycles:uppp', Event count (approx.): 811063902
  Children      Self  Command  Shared Object       Symbol
+   98.33%     0.00%  bc       [unknown]           [.] 0x771e258d4c544155
+   98.33%     0.00%  bc       libc-2.27.so        [.] __libc_start_main
+   98.33%     0.00%  bc       bc                  [.] main

b c калькулятор с графиком гномьих вызовов:

$ echo '3^123456%3' | perf record --call-graph dwarf  bc/bc
$ perf report
Samples: 1K of event 'cycles:uppp', Event count (approx.): 898828479
  Children      Self  Command  Shared Object     Symbol
+   98.42%     0.00%  bc       bc                [.] _start
+   98.42%     0.00%  bc       libc-2.27.so      [.] __libc_start_main
+   98.42%     0.00%  bc       bc                [.] main

b c без отладочной информации имеет некорректную обработку графа вызовов с помощью perf в режиме -g (fp) (нет 99% для основного):

$ cp bc/bc bc.strip
$ strip -d bc.strip
$ echo '3^123456%3' | perf record --call-graph fp ./bc.strip 
Samples: 1K of event 'cycles:uppp', Event count (approx.): 841993392
  Children      Self  Command   Shared Object     Symbol
+   43.94%    43.94%  bc.strip  bc.strip          [.] _bc_rec_mul
+   39.73%    39.73%  bc.strip  bc.strip          [.] _bc_shift_addsub.isra.3
+   11.27%    11.27%  bc.strip  bc.strip          [.] _bc_do_sub
+    0.92%     0.92%  bc.strip  libc-2.27.so      [.] malloc

Иногда perf report --no-children может быть полезно для отключения сортировки по self + children накладные расходы (будут отсортированы по «собственным» накладным расходам), например, когда граф вызовов не был полностью захвачен.

...