Ответ 1
gprof не использует эту функцию для синхронизации, входа или выхода, но для подсчета вызовов функции A вызывает любую функцию B. Скорее, он использует свое время, собранное путем подсчета выборок ПК в каждой подпрограмме, а затем использует подсчет вызовов функций для работы, чтобы оценить, сколько из этого времени самообмена должно быть возвращено абонентам.
Например, если A называет C 10 раз, а B называет C 20 раз, а C имеет 1000 мс собственного времени (т.е. 100 образцов ПК), тогда gprof знает, что C вызывается 30 раз, а 33 из образцов могут заряжаться до А, в то время как другие 67 могут быть заряжены до Б. Аналогично, количество экземпляров распространяется по иерархии вызовов.
Итак, вы видите, что это не время входа и выхода функции. Измерения, которые он получает, очень грубые, поскольку он не делает различий между короткими вызовами и длительными вызовами. Кроме того, если образец ПК происходит во время ввода-вывода или в библиотечной программе, которая не скомпилирована с -pg, она не учитывается вообще. И, как вы отметили, он очень хрупкий при наличии рекурсии и может ввести заметные накладные расходы на короткие функции.
Другим подходом является выборка в стеке, а не выборка ПК. Конечно, дороже захватывать образец стека, чем образец ПК, но требуется меньшее количество выборок. Если, например, функция, строка кода или любое описание, которое вы хотите сделать, видно на фракции F из общего количества N выборок, то вы знаете, что доля времени, в течение которого она стоит, равна F со стандартным отклонением of sqrt (NF (1-F)). Так, например, если вы берете 100 выборок, а строка кода отображается на 50 из них, то вы можете оценить стоимость линии в 50% случаев с неопределенностью sqrt (100 *.5 *.5) = +/- 5 образцов или от 45% до 55%. Если вы берете в 100 раз больше образцов, вы можете уменьшить неопределенность в 10 раз. (Рекурсия не имеет значения. Если функция или строка кода появляются 3 раза в одном образце, это считается как 1 образец, а не 3. Также не имеет значения, являются ли вызовы функций короткими - если их называют достаточно временными, чтобы стоить значительную долю, они будут пойманы.)
Обратите внимание, что когда вы ищете вещи, которые вы можете исправить, чтобы получить ускорение, точный процент не имеет значения. Важно найти его. (На самом деле вам нужно только дважды увидеть проблему, чтобы знать, что она достаточно большая, чтобы исправить.)
Этот этот метод.
P.S. Не присоединяйтесь к графам вызовов, горячим путям или горячим точкам. Здесь типичное гнездо крысы-графа. Желтый - это горячая дорожка, а красный - горячая точка.
И это показывает, насколько легко для сочной возможности ускорения быть ни в одном из этих мест:
Самое ценное, на что можно обратить внимание, - это дюжина случайных выборок сырого стека и привязка их к исходному коду. (Это означает, что вы обходите заднюю часть профилировщика.)
ADDED: просто чтобы показать, что я имею в виду, я смоделировал десять образцов стека из графика вызовов выше, и вот что я нашел
- 3/10 образцов вызывают
class_exists
, один для получения имени класса, и два для настройки локальной конфигурации.class_exists
вызываетautoload
, который вызываетrequireFile
, а два из них вызываютadminpanel
. Если это можно сделать более прямо, это может сэкономить около 30%. - 2/10 сэмплы вызывают
determineId
, который вызываетfetch_the_id
, который вызываетgetPageAndRootlineWithDomain
, который вызывает еще три уровня, заканчивающихся наsql_fetch_assoc
. Кажется, что у вас много проблем, чтобы получить идентификатор, и это стоит около 20% времени, и что не считая ввода/вывода.
Таким образом, образцы стека не просто говорят вам, сколько всего времени стоит функция или строка кода, они рассказывают вам, почему это делается, и какую возможную глупость требуется для ее выполнения. Я часто вижу это - галопирующую общность - размахивание мухами с молотками, а не преднамеренно, но только после хорошего модульного дизайна.
ДОБАВЛЕНО: Еще одна вещь, которую нельзя всасывать, - это графики пламени.
Например, здесь приведен график графа пламени (повернутый на 90 градусов) из десяти смоделированных выборок стека из графика вызовов выше. Все подпрограммы нумеруются, а не называются, но каждая процедура имеет свой собственный цвет.
Обратите внимание, что проблема, указанная выше, с class_exists (процедура 219), которая находится на 30% образцов, совершенно не очевидна, глядя на график пламени.
Больше образцов и разных цветов сделают график более "пламенным", но не выставляют процедуры, которые занимают много времени, вызывая много раз из разных мест.
Здесь одни и те же данные сортируются по функции, а не по времени.
Это немного помогает, но не объединяет сходства, вызванные из разных мест:
И снова цель состоит в том, чтобы найти проблемы, которые скрываются от вас.
Любой может найти легкий материал, но проблемы, которые скрываются, - это те, которые имеют значение.
ДОБАВЛЕНО: Еще один вид глазной конфеты - это:
где чернокожие подпрограммы могут быть одинаковыми, просто вызванными из разных мест.
Диаграмма не сводит их для вас.
Если процедура имеет высокий инклюзивный процент, вызывая большое количество раз из разных мест, она не будет отображаться.