gprof на самом деле довольно примитивно. Вот что он делает.
1) Сэмплирует программный счетчик с постоянной скоростью и записывает, сколько сэмплов попадает в каждую функцию (исключительное время).
2) Подсчитывает, сколько раз любая функция A вызывает любую функцию B.
Исходя из этого, он может узнать, сколько раз каждая функция была вызвана в целом, и каково ее среднее исключительное время.
Чтобы получить среднее время включения каждой функции, оно распространяет исключительное время вверх в графе вызовов.
Если вы ожидаете, что это будет иметь какую-то точность, вы должны знать о некоторых проблемах.
Во-первых, он учитывает только время ЦП, т. Е. Не учитывает ввод-вывод или другие системные вызовы.
Во-вторых, рекурсия смущает это.
В-третьих, предпосылка о том, что функции всегда придерживаются среднего времени выполнения, независимо от того, когда они вызваны или кто их вызывает, весьма сомнительна.
В-четвертых, представление о том, что функции (и их граф вызовов) - это то, о чем вам нужно знать, а не о строках кода, является просто популярным предположением, не более того.
В-пятых, представление о том, что точность измерения даже имеет отношение к нахождению «узких мест», также является популярным предположением, не более того.
Callgrind может работать на уровне линий - это хорошо. К сожалению, он разделяет другие проблемы.
Если ваша цель состоит в том, чтобы найти «узкие места» (в отличие от получения общих измерений), вам следует взглянуть на стенные сэмплеры временного времени, которые выдают процентные значения, такие как Zoom,
Причина проста, но, возможно, незнакома.
Предположим, у вас есть программа с набором функций, вызывающих друг друга, что занимает в общей сложности 10 секунд. Кроме того, есть сэмплер, который производит выборку не только счетчика программы, но и всего стека вызовов, и он делает это все время с постоянной скоростью, например, 100 раз в секунду. (Пока игнорировать другие процессы.)
Итак, в конце у вас есть 1000 образцов стека вызовов.
Выберите любую строку кода L, которая появляется на более чем одном из них.
Предположим, вы могли бы как-то оптимизировать эту строку, избегая ее, удаляя ее или передавая ее действительно очень быстрому процессору.
Что будет с этими образцами?
Поскольку эта строка кода L теперь не занимает (по существу) совсем никакого времени, ни одна выборка не может поразить ее, поэтому эти выборки просто исчезнут , уменьшая общее количество выборок и, следовательно, общее время. !
Фактически, общее время будет уменьшено на долю времени, которое L находился в стеке, что примерно равно части выборок, которые его содержали.
Я не хочу получать слишком статистические данные, но многие люди думают, что вам нужно много выборок, потому что они считают, что точность измерения важна.
Это не так, если причина, по которой вы делаете это, состоит в том, чтобы выяснить, что нужно исправить, чтобы ускориться.
Акцент делается на нахождение , что исправить, а не на измерение это.
Линия L находится в стеке в некоторой доле F времени, верно?
Таким образом, каждый образец имеет вероятность F попадания в него, верно? Так же, как подбрасывание монеты.
Существует теория об этом, называемая Правило наследования .
Это говорит о том, что (при упрощенных, но общих предположениях), если вы подбрасываете монету N раз и видите «головы» S раз, вы можете оценить справедливость монеты F как (в среднем) (S+1)/(N+2)
.
Итак, если вы берете всего лишь три выборки и видите L на двух из них, знаете ли вы, что такое F? Конечно, нет.
Но вы делаете в среднем знаете, что это (2 + 1) / (3 + 2) или 60% .
Так вот, сколько времени вы могли бы сэкономить (в среднем), "оптимизируя" строку L.
И, конечно же, образцы стеков показали, что точно , где находится линия L ("узкое место" **).
Действительно ли имело значение, что вы не измеряли его до двух или трех десятичных знаков?
Кстати, он невосприимчив к всем другим проблемам, упомянутым выше .
** Я продолжаю помещать кавычки вокруг "узкого места", потому что то, что делает большинство программного обеспечения медленным, не имеет ничего общего с горлышком бутылки.Лучшая метафора - это «утечка» - то, что просто напрасно тратит время.