Несколько лет назад я написал профилировщик для запуска под DOS.
Если вы используете KCacheGrind, вот что я хотел бы сделать. Это может быть не слишком сложно написать, или вы можете просто сделать это вручную.
KCacheGrind имеет кнопку панели инструментов «Force Dump», с помощью которой вы можете запускать дамп вручную в произвольное время. Захват трассировки стека в случайном или псевдослучайном времени, в интервале, когда вы ожидаете программу, является сердцем техники.
Не так много образцов необходимо - 20 обычно более чем достаточно. Если узкое место стоит большой суммы, например, более 50%, может быть достаточно 5 образцов.
Обработка образцов очень проста. Каждая трассировка стека состоит из серии строк кода (фактически адресов), где все, кроме последних, являются вызовами функции/метода.
Соберите список всех строк кода, которые появляются на выборках, и устраните дубликаты.
Для каждой строки кода подсчитывайте, какая часть образцов отображается. Например, если вы берете 20 выборок, а строка кода отображается на 3 из них, даже если она появляется несколько раз в некоторой выборке (из-за рекурсии), счет составляет 3/20 или 15%. Это прямая мера стоимости каждого заявления.
Показать наиболее дорогостоящие 100 строк кода. Ваши узкие места находятся в этом списке.
То, что я обычно делать с этой информацией, выбирают линию с высокой стоимостью, а затем вручную взять образцы стека до тех пор, пока не появится (или смотреть на те, которые я уже получил), и спрашиваю себя: «Почему он делает эту строку кода не только в местном смысле, но и в глобальном смысле ». Другой способ выразить это: «Что в глобальном смысле было программой, пытающейся выполнить в то время срез, когда этот образец был взят». Причина, по которой я спрашиваю об этом, заключается в том, что это говорит мне, действительно ли нужно тратить расходы на эту линию.
Я не хочу критиковать все большие рабочие человек развиваются профайлерами, но, к сожалению, есть много прочно закрепились миф на эту тему, в том числе:
, что точное измерения, с большое количество образцов, важно. Скорее акцент должен быть сделан на нахождении узких мест. Точное измерение не является обязательным условием для этого. Для типичных узких мест, стоимость которых составляет от 10% до 90%, измерение может быть довольно грубым.
, что функции имеют значение, отличное от строк кода. Если вы найдете дорогостоящую функцию, вам все равно придется искать в ней строки, которые являются узким местом. Эта информация находится прямо там, в трассировке стека - нет необходимости охотиться за ней.
что вам нужно отличить CPU от времени настенных часов. Если вы этого ждете, это время настенных часов (время наручных часов?). Если у вас есть узкое место, состоящее из посторонних операций ввода-вывода, например, вы хотите игнорировать это, потому что это не процессорное время?
что разница между исключительным временем и включенным временем полезна. Это имеет смысл только в том случае, если вы выполняете функции синхронизации, и вам нужно понять, тратится ли время не на вызовы. Если вы посмотрите на строки кода, единственное, что имеет значение, - это инклюзивное время. Другой способ сказать, что каждая инструкция является инструкцией вызова, даже если она вызывает только микрокод.
что рекурсия имеет значение. Это не имеет значения, потому что это не влияет на долю выборок, на которые идет линия, и поэтому отвечает.
, что счетчик вызовов линии или функции имеет значение. Является ли это быстрым и называется слишком много раз, или медленным и называется один раз, стоимость - это процент времени, который он использует, и это то, что оценивают образцы стека.
это выполнение вопросов отбора проб. Я не против брать образец стека и смотреть на него в течение нескольких минут, прежде чем продолжить, полагая, что это не делает узкие места движущимися.
Here's более полное объяснение.