Как я могу получить лучшее профилирование? - PullRequest
4 голосов
/ 07 марта 2009

Мне нужно профилировать программу, чтобы увидеть, нужно ли вносить какие-либо изменения в отношении производительности. Я подозреваю, что есть необходимость, но измерение в первую очередь - это путь. Это не та программа, но она иллюстрирует мою проблему:

#include <stdio.h>
int main (int argc, char** argv)
{
  FILE* fp = fopen ("trivial.c", "r");
  if (fp)
  {
    char line[80];
    while (fgets (line, 80, fp))
      printf (line);

    fclose (fp);
  }
  return 0;
}

Вот что я с ним сделал:

% gcc trivial.c -pg -o trivial
% ./trivial
...
% gprof trivial gmon.out

Конечно, это тривиальная программа, но я бы подумал, что это сделает какой-то проблеск на радаре профилирования. Это не:

                                  called/total       parents 
index  %time    self descendents  called+self    name       index
                                  called/total       children

                0.00        0.00       1/1           __start [1704]
[105]    0.0    0.00        0.00       1         _main [105]

-----------------------------------------------

  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
  0.0       0.00     0.00        1     0.00     0.00  _main [105]

Index by function name

 [105] _main              

Кто-нибудь может направить меня сюда? Мне бы хотелось, чтобы выходные данные отражали то, что они вызывали fgets и printf как минимум 14 раз, и все-таки он попал на диск - наверняка должно быть некоторое измеренное время.

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

Возможно, gprof не подходит для использования. Что такое?

Это на OS X Leopard.

Редактировать: я запустил настоящую программу и получил это:

% time real_program
real      4m24.107s
user      2m34.630s
sys       0m38.716s

Ответы [ 9 ]

5 голосов
/ 07 марта 2009

По умолчанию gprof показывает ограниченные данные. И это хорошо. Посмотрите на ваш вывод - он упоминает только основной (по умолчанию). Теперь посмотрите на столбец calls - это то, что вы хотите. Но для других функций попробуйте:

gprof -e main -f printf -f fgets trivial > gprof.output

Вот ссылка на некоторые команды. Также попробуйте man gprof в вашей системе. Здесь как интерпретировать данные.

Кроме того, посмотрите также ltrace, strace и ptrace (если доступно - я больше не помню, все ли они на OSX) - они забавные!

5 голосов
/ 07 марта 2009

Я думаю, что вы можете попробовать различные инструменты Valgrind, особенно callgrind (используется для подсчета количества звонков и включенной стоимости за каждый звонок в вашей программе).

Существуют различные приятные инструменты визуализации для вывода valgrind. Я не знаю о конкретных инструментах для OS X, хотя.

3 голосов
/ 07 марта 2009

Перед профилированием вашего кода вы должны увидеть, где ваша программа тратит свое время. Запустите его под временем (1), чтобы увидеть соответствующее время пользователя, системы и настенных часов. Профилирование вашего кода имеет смысл только тогда, когда время пользователя близко к времени настенных часов. Если пользовательское и системное время очень мало по сравнению со временем настенных часов, то ваша программа привязана к вводу / выводу; если системное время близко к времени настенных часов, ваша программа привязана к ядру. В обоих этих случаях запустите вашу программу с помощью strace -c или подходящего сценария dtrace, чтобы определить время, затраченное на каждый системный вызов.

3 голосов
/ 07 марта 2009

Shark - это профилировщик, включенный в инструменты разработчика.

2 голосов
/ 07 марта 2009

Профилирование не указывает на доступ к диску, только то, какие функции были вызваны, и они не будут репрезентативными из-за кэширования виртуальной машины.

Valgrind плохо работает на OS X.

С Leopard у вас есть утилита Dtrace ; Я не использовал его, но он может дать вам информацию, которую вы ищете.

1 голос
/ 09 марта 2009

Посмотрите на вашу программу, поскольку вы используете обработку файлов (только), это также зависит от того, какой кеш включен. Итак, будьте осторожны, ваши результаты профилирования могут отличаться в зависимости от поведения вашего кэша.

1 голос
/ 07 марта 2009

Отсутствие определенных функций обычно означает, что эти функции не скомпилированы для профилирования. В частности, для профилирования кода, который использует стандартные функции, такие как printf (я думаю, почти всегда), вам нужна версия библиотеки C, которая компилируется с поддержкой профилирования. Я не знаком с OS X, но в Linux мне нужно было установить пакет libc6-prof, который включает библиотеку libc_p.

B.t.w., Я верю, что OS X (или, возможно, XCode?) Поставляется с инструментом профилирования. Он не такой точный, как метод gprof, потому что он использует выборку, но вы можете запустить его в любой программе без специальной компиляции.

0 голосов
/ 15 июня 2009

Для примера кода, который вы дали выше, если вы сэмплируете стек вызовов несколько раз, вы в основном увидите эти стеки в некоторой пропорции:

-------------------------------------
...
main.c:  4 call _fopen
...        call _main
-------------------------------------
...
main.c:  8 call _fgets
...        call _main
-------------------------------------
...
main.c:  9 call _printf
...        call _main
-------------------------------------
...
main.c: 11 call _fclose
...        call _main

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

0 голосов
/ 08 марта 2009

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

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

Это сверху вниз. Это связано с верой в то, что лес важнее деревьев. Он основан на мифах о «скорости кода» и «узких местах». Это не очень научно.

Проблема с производительностью больше похожа на ошибку, чем на количественную. То, что он делает неправильно, это тратит время , и это нужно исправить. Он основан на простом наблюдении:

Медлительность состоит из времени, потраченного по плохим причинам.

Чтобы найти его, произведите выборку состояния программы в случайных промежутках времени и выясните их причины.

Если что-то вызывает медлительность, то один этот факт выставляет это вашим образцам. Так что, если вы берете достаточно образцов, вы увидите это. Вы будете приблизительно знать, сколько времени это будет стоить вам, по доле образцов, которые это показывают.

Хороший способ узнать, тратится ли время на небольшую вескую причину, - внимательно посмотреть на стек вызовов. У каждого вызова функции в стеке есть неявная причина, и если какая-либо из этих причин плохая, то причина для всей выборки плохая.

Некоторые профилировщики говорят вам, на уровне выписки, сколько стоит каждое утверждение.

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

Вы можете сказать: «Это не точно». Это очень точно. Он точно определяет инструкции, вызывающие проблему. Это не дает вам 3 десятичных знака точности синхронизации. То есть это мерзко для измерения, но превосходно для диагностики.

Вы можете сказать: «А как насчет рекурсии?». Ну что на счет этого?

Вы можете сказать: «Я думаю, что это может работать только на игрушечных программах». Это было бы просто желание. На самом деле большие программы, как правило, имеют больше проблем с производительностью, потому что у них более глубокие стеки, что дает больше возможностей для вызовов по плохим причинам, и выборка находит их просто отлично, спасибо.

Извините, что я обманщик. Я просто не хочу видеть мифы в том, что должно быть научно обоснованным.

MORE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...