Как профилировать мое приложение на С++ в Linux

Я хотел бы профилировать мое приложение С++ на linux. Я хотел бы узнать, сколько времени мое приложение потратило на обработку ЦП и время, затраченное на блокирование IO/бездействия.

Я знаю, что в linux есть инструмент для вызова valgrind. Но это ломает время, затрачиваемое на каждый метод, и это не дает мне общую картину того, сколько времени потрачено на обработку ЦП против простоя? Или есть способ сделать это с помощью valgrind.

Ответы

Ответ 1

Я могу порекомендовать valgrind callgrind инструмент в сочетании с KCacheGrind для визуализации. KCacheGrind позволяет легко видеть, где находятся горячие точки.

Примечание. С тех пор я использовал его слишком долго, поэтому я не уверен, что вы сможете получить время ожидания ввода-вывода. Возможно, в сочетании с iostat или pidstat вы сможете увидеть, где все время было потрачено.

Ответ 2

Проверьте oprofile. Кроме того, для большей диагностики на уровне системы попробуйте systemtap.

Ответ 3

Возможно, вы захотите проверить Zoom, который является намного более полированным и полнофункциональным, чем oprofile et al. Это стоит денег ($ 199), но вы можете получить бесплатную 30-дневную оценочную лицензию.

Ответ 4

LTTng - хороший инструмент для полного профилирования системы.

Ответ 5

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

Это даст вам что-то вроде:

real    0m1.412s
user    0m1.288s
sys     0m0.056s

В этом случае учетная запись пользователя + sys (ядро) составляет почти все время реального времени, а всего 0,068 с неучтенным для... (возможно, время, затраченное на первоначальную загрузку приложения и поддерживающих его lib).

Однако, если вы увидите:

real    0m5.732s
user    0m1.144s
sys     0m0.078s

тогда ваше приложение потратило 4.51s, не потребляя процессор и предположительно заблокировав IO. Какую информацию я думаю, что вы ищете.

Однако, когда этот простой метод анализа ломается, это:

  • Приложения, которые ждут таймер/часы или другие внешние стимулы (например, управляемые событиями графические приложения). Он не может различать время ожидания на часах и время ожидания на диске/сети.
  • Многопоточные приложения, которым нужно немного подумать о том, чтобы интерпретировать номера.

Ответ 6

callgrind - очень хороший инструмент, но я нашел OProfile для меня более "полным". Кроме того, это единственный, который позволяет вам указать модуль и/или источник ядра, чтобы глубже понять ваши узкие места. Предполагается, что выход может взаимодействовать с KCacheGrind, но у меня были проблемы с этим, поэтому я использовал Gprof2Dot. Вы можете экспортировать свой callgraph в .png.

Edit:

OProfile просматривает общую систему, поэтому процесс будет следующим:

[setup oprofile]

opcontrol --init
opcontorl --vmlinux=/path/to/vmlinux     (or --no-vmlinux)
opcontrol --start

[запустите ваше приложение здесь]

opcontrol --stop   (or opcontrol --shutdown [man for difference]

затем, чтобы начать просмотр результатов, посмотрите man-страницу в opreport

Ответ 7

Инструменты лакей и/или helgrind в valgrind должны позволить вам сделать это.

Ответ 8

google-perf-tools - гораздо более быстрая альтернатива callgrind (и она может генерировать выходные данные в том же формате, что и callgrind, поэтому вы можете использовать KCacheGrind).

Ответ 9

Смотрите это сообщение.

И этот пост.

В принципе, между тем, как начинается программа и когда она заканчивается, у нее есть стек вызовов. Во время ввода-вывода стек заканчивается системным вызовом. Во время вычисления он заканчивается типичной инструкцией.

В любом случае, если вы можете выборочно отбирать стек случайными часами, вы можете точно увидеть, почему он тратит это время.

Единственная оставшаяся точка - тысячи образцов могут дать чувство уверенности, но они не скажут вам больше, чем 10 или 20 образцов.