Использование gprof с сокетами

У меня есть программа, которую я хочу профилировать с gprof. Проблема (похоже) в том, что он использует сокеты. Итак, я получаю такие вещи:

::select(): Interrupted system call

Я решил эту проблему некоторое время назад, сдался и пошел дальше. Но я бы очень хотел иметь возможность профилировать свой код, используя gprof, если это возможно. Что я могу сделать? Мне не хватает опции gprof? Опция сокета? Является ли gprof полностью бесполезным при наличии таких системных вызовов? Если так, есть ли жизнеспособная альтернатива?

РЕДАКТИРОВАТЬ: Платформа:

  • Linux 2.6 (x64)
  • GCC 4.4.1
  • gprof 2.19

2 ответа

Решение

Код сокета должен обрабатывать прерванные системные вызовы независимо от профилировщика, но под профилировщиком это неизбежно. Это значит иметь код вроде

if ( errno == EINTR ) { ...

после каждого системного вызова.

Взгляните, например, здесь для фона.

gprof ( вот статья) надежен, но он предназначен только для измерения изменений, и даже для этого он измеряет только проблемы, связанные с процессором. Он никогда не рекламировался, чтобы быть полезным для выявления проблем. Это идея, которую другие люди наслаивали на нее.

Рассмотрим этот метод.

Еще одним хорошим вариантом, если вы не против потратить немного денег, является Zoom.

Добавлено: если я могу просто дать вам пример. Предположим, у вас есть иерархия вызовов, в которой Main вызывает A некоторое количество раз, A вызывает B некоторое количество раз, B вызывает C некоторое количество раз, и C ожидает некоторый ввод-вывод с сокетом или файлом, и это в основном все программа делает. Теперь предположим, что количество раз, когда каждая подпрограмма вызывает следующую, на 25% больше, чем необходимо. Поскольку 1.25^3 составляет около 2, это означает, что запуск всей программы занимает вдвое больше времени, чем нужно.

Во-первых, поскольку все время тратится на ожидание ввода-вывода, gprof ничего не скажет вам о том, как это время тратится, потому что оно смотрит только на "рабочее" время.

Во-вторых, предположим (только для аргумента), что он действительно посчитал время ввода-вывода. Это может дать вам график вызовов, в основном говоря, что каждая подпрограмма занимает 100% времени. О чем тебе это говорит? Ничего больше, чем вы уже знаете.

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

Люди получают большие факторы таким образом. По моему опыту, количество уровней вызовов может легко быть 30 или более. Каждый звонок кажется необходимым, пока вы не спросите, можно ли его избежать. Даже небольшое количество вызовов, которых можно избежать, может оказать огромное влияние на такое количество слоев.

Другие вопросы по тегам