Как профилировать мое приложение на С++ в 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 образцов.