Я пытаюсь использовать Callgrind / Kcachegrind в первый раз для профилирования моего приложения C ++, и я заметил, что две функции, которые занимают больше времени:
Теперь, из моего понимания, цикл 1 связан с оценкой времени, затрачиваемого рекурсивно вызываемыми функциями, но мне не очень понятно, как мне следует интерпретировать столь большое время, проведенное здесь. Если есть несколько циклов, я хотел бы видеть, какая функция вызывается чаще и занимает больше процессорного времени в конце. Если я отключу обнаружение циклов (View-> Cycle Detection), цикл 1 исчезнет, но время «Self» составит примерно 60%, и я не уверен, что это лучше всего сделать.
Что касается do_lookup_x, я совершенно невежественен …
Можете ли вы объяснить мне немного, как я должен интерпретировать эти результаты?
Заранее спасибо.
Циклы могут быть обнаружены неправильно в KCachegrind:
http://valgrind.org/docs/manual/cl-manual.html#cl-manual.cycles
6.2.4. Избегать циклов
Неформально говоря, цикл — это группа функций, которые рекурсивно вызывают друг друга. …Циклы сами по себе неплохие, но они усложняют анализ производительности вашего кода. Это потому, что инклюзивные расходы на звонки внутри цикла бессмысленны. Определение инклюзивной стоимости, то есть собственной стоимости функции плюс инклюзивная стоимость ее вызываемых абонентов, требует топологического порядка среди функций. Для циклов это не так: вызываемые функции в цикле включают саму функцию. Поэтому KCachegrind выполняет обнаружение циклов и пропускает визуализацию любых включенных затрат для вызовов внутри циклов. Кроме того, все функции в цикле свернуты в искусственные функции, называемые циклом 1.
Теперь, когда программа предоставляет действительно большие циклы (как это верно для некоторого кода GUI, или в общем коде, использующем стиль программирования на основе событий или обратных вызовов), вы теряете свойство nice, позволяющее вам определять узкие места, следуя цепочкам вызовов из main, guided через включенную стоимость. Кроме того, KCachegrind теряет способность показывать интересные части графа вызовов, так как использует инклюзивные расходы для отключения неинтересных областей.
Несмотря на бессмысленность инклюзивных затрат в циклах, большой недостаток визуализации мотивирует возможность временно отключить обнаружение циклов в KCachegrind, что может привести к неправильной визуализации. Однако часто циклы появляются из-за неудачной суперпозиции независимых цепочек вызовов таким образом, что результат профиля будет видеть цикл. Пренебрежение неинтересными звонками с очень малой измеренной инклюзивной стоимостью нарушит эти циклы. В таких случаях неправильная обработка циклов, не обнаруживая их, все еще дает значительную визуализацию профилирования.
Попробуйте отключить Cycle Detection в меню View KCachegrind и проверьте столбец времени «Self», так как «Incl» будет неправильным.
Вы также можете попробовать другой профилировщик с точной и полной функцией сохранения стека. Многие профилировщики поддерживаются https://github.com/jrfonseca/gprof2dot Скрипт сохраняет полный стек, а не только пары вызывающий-вызывающий, как в формате callgrind / cachegrind.
Я согласен с @osgx, что вам нужен другой профилировщик, который захватывает все стеки вызовов.
Тогда процент времени включения функции является очень простым числом.
Это просто доля выборок из стека, в которой эта функция появляется, независимо от того, сколько раз она появляется в отдельных выборках.
Вот способ думать об этом.
— Предположим, что образцы берутся каждые 10 мс, всего 100 секунд или 10000 образцов.
— Предположим, что функция Foo появляется на 30% этих выборок, один или несколько раз.
— Это означает, что если бы вы могли изменить Foo так, чтобы он занимал почти нет времени, например, передав его очень быстрому субпроцессору, тогда никакие сэмплы не увидят его, потому что он никогда не будет в стеке достаточно долго, чтобы сэмпл попадал Это.
— Так что эти 30% образцов просто исчезать, и программа заняла бы 70 секунд вместо 100.
— Это означает, что Foo несет личную ответственность за 30% времени (независимо от рекурсии).
На самом деле, я предпочитаю Этот метод, потому что меня больше интересует выяснение, в чем проблема, а не то, занимает ли она 29% или 31%.
Требуется все, что требуется, и то, что требуется, не будет зависеть от того, насколько точно это будет измерено.