По умолчанию, при первом получении профиля программы параметр Callers (Вызывающие подпрограммы) для всех маркеров «области» типа «точка входа в подпрограмму» имеет значение None (Никакие).
Установка параметра Statistics| Callers (Статистика| Вызывающие подпрограммы), находящегося в главном меню, в состояние Enable (Включено) равнозначна установке значения All Callers (Все вызывающие подпрограммы) параметра Сallers (Вызывающие подпрограмм) для каждого маркера «области», установленного в окне Areas («Области»). Тем не менее, если Вы вручную установили значения параметров Callers (Вызывающие подпрограмм) для каких-либо «областей» в окне Areas («Области»), то, в этом случае, установка параметра Statistics| Callers (Статистика| Вызывающие подпрограммы) в состояние Enable (Включено), не изменит значение параметра Callers (Вызывающие подпрограммы) для таких «областей».
Установка параметра Statistics| Callers (Статистика| Вызывающие подпрограммы) в некоторой точке программы в состояние Disable (Отключено) указывает профилировщику, чтобы он не сохранял никакой информации из стека вызовов, но это совершенно не влияет на действие параметров Caller (Вызывающая подпрограмма), установленных в окне Areas («Области») (как и при установке данного параметра в состояние Enable (Включено)).
Опрос вместо подсчета.
На самом деле, профилировщик не измеряет время непосредственно, а очень точно вычисляет его на основании информации о количестве прерываний таймера.
Этот способ подсчета времени можно рассматривать как один из видов статистического моделирования (некий статистический опрос).
Периодически запрашивая, какая из «областей» является текущей, и, имея для каждой из «областей» счетчик, (который увеличивается при каждом прерывании таймера, если в этот момент «область» является текущей), профилировщик может вычислить время, затраченное на выполнение данной «области».
Примечание: Все вышесказанное имеет место только в случае работы в пассивном режиме профилирования.
Профилировщику известно общее время выполнения программы.
Также ему известно общее число прерываний таймера, произошедших во время выполнения программы. Время, затраченное на выполнение данной «области» может быть вычислено по формуле:
<время выполнения «области»> = <общее время выполнения программы> * <значение счетчика «области»> / <значение счетчика программы>
Но, на самом деле, нельзя утверждать, что значение времени, вычисленное по приведенной формуле, в точности совпадает с количеством времени, затраченным на выполнение данной «области». Если Ваша программа содержит в себе цикл, в котором, с частотой, кратной частоте прерывания таймера происходит обращение к некоторой подпрограмме (например к подпрограмме генерации звука одной тональности), то большинство моментов времени, в которые будут генерироваться импульсы таймера может прийтись на выполнения некоторой строки (или «области»). Описанное явление резонанса может возникнуть даже в случае, когда рассматриваемая строка не принадлежит к числу основных потребителей времени выполнения Вашей программы. Подобные ситуации редки, но вполне возможны.
Если Вы подозреваете, что возникла подобная ситуация с наложением частот, то измените значение параметра Statistics|
Profiling Options| Clock speed value (Статистика| Параметры профилирования| Скорость работы часов) и сравните профиль, полученный после внесения этого изменения, с предыдущим профилем.
Использование памяти профилировщиком.
На следующем рисунке показано распределение памяти при получении профиля программы с помощью системы Turbo Profiler.
Рис. 2.2 Карта памяти системы Turbo Profiler.
Для запоминания информации об «областях» профилировщик использует динамически-распределяемую область памяти (far heap).
Если Вы, в процессе выполнения программы, добавите новые «области», то эта, динамически-распределяемая область памяти, может распространиться на ту часть памяти, которая зарезервирована для программы пользователя, для того, чтобы разместить в ней новые переменные «областей» и буферы. Поэтому, если Вы вносите изменения в разметку «областей» во время выполнения программы, Вам необходимо повторно запустить программу с помощью Run| Program Reset (Выполнение| Повторное выполнение программы). Если Вы этого не сделаете, то результаты профилирования будут совершенно непредсказуемы, Ваш компьютер может просто «зависнуть».
Если Вы думаете, что процесс совершенствования Вашей программы при помощи профилирования состоит всего лишь из трех последовательных этапов на первом из которых вы получаете профиль программы, на втором — модифицируете исходный текст Вашей программы, а на третьем — уже празднуете победу, то Вы глубоко заблуждаетесь. Профилирование Ваших программ в системе Turbo Profiler с целью повышения их быстродействия — это динамичный интерактивный процесс. Вы собираете статистику, анализируете данные о процессе выполнения, находящиеся в разнообразных окнах, возможно, изменяете какие-то параметры профилирования для получения новых данных, профилируете еще раз, снова проводите анализ статистики, модифицируете исходный текст и компилируете его, опять получаете профиль программы, затем анализируете статистику и так далее.
Если Вы поначалу не уверены в своих предположениях о том, какие из участков Вашей программы являются ее «узкими местами», то, при помощи системы Turbo Profiler, получите ее профиль с теми значениями параметров профилирования, которые установлены по умолчанию. После этого, посмотрев на результаты профилирования, появившиеся в окне Execution Profile (Профиль выполнения), Вы получите представление о том, какие из подпрограмм Вашей программы потребляют большую часть времени ее выполнения. Сопоставив временные и количественные данные, Вы поймете какие участки Вашей программы наиболее дорогостоящи в смысле времени, затрачиваемого на одно выполнение. Вооруженные этими знаниями, Вы можете смело начинать атаку неэффективных участков Вашей программы.
Система Turbo Profiler имеет несколько различных окон отчета, предназначенных для изображения и анализа полученных статистических данных. Также Вы можете распечатать содержимое такого окна на бумаге, либо записать его на диск для учета этапов повышения быстродействия Вашей программы. В окнах отчета Вы можете увидеть количественную и временную информацию о процессе выполнения Вашей программы, данные о ее работе с файлами, информацию об использовании прерываний DOS, работе механизма оверлеев, а также о вызовах подпрограмм.
Как же Вам распорядиться всей этой мощностью и гибкостью? Как использовать систему Turbo Profiler наиболее оптимальным образом и получать при этом максимальную отдачу? В чем заключаются хитрости профилирования? Очевидно, что в этой главе мы просто не сможем исчерпывающе ответить на все поставленные вопросы. Но, тем не менее, мы опишем некоторые основные принципы, приемы и стратегии для того, чтобы придать Вам начальное ускорение.
Примечание: Вы можете обратиться к большому количеству книг и статей, содержащих общие сведения о профилировании.
При получении первого профиля Вашей программы система Turbo Profiler производит следующие действия:
* автоматически просматривает текст Вашего EXE-файла в поисках головного модуля Вашей программы;
* устанавливает маркеры «областей» для Вашей программы;
* определяет какой из из модулей исходного текста Вашей программы содержит в себе ее головную часть;
* загружает этот головной модуль в окно Module (Модуль);
* устанавливает курсор на начальную точку головного модуля.
Модуль исходного текста Вашей программы является головным в том случае, если он содержит в себе строку, выполняющуюся самой первой после запуска программы. Маркеры «областей» отмечают участки Вашей программы, для которых Вы хотите собрать статистические данные. Число установленных маркеров зависит от количества символических имен, найденных в отладочной информации Вашей программы.
И всякий раз, когда Вы выходите из системы Turbo Profiler происходит автоматическое сохранение информации о «областях», помеченных в Вашей программе, в файле с именем TFA, где совпадает с именем Вашей программы. Каждый раз при загрузке Вашей программы в систему Turbo Profiler происходит поиск соответствующего файла с расширением. TFA, и, в случае наличия такого файла, происходит автоматическое задание «областей» на основании имеющейся в данном файле информации.
Также Вы можете сохранить результаты профилирования в файле с расширением. TFS, используя для этого команду Statistics| Save (Статистика| Сохранить). По умолчанию, имя такого файла будет иметь вид: TFS. Вы можете воспользоваться именем, задаваемым по умолчанию, либо изменить его (в том случае, если Вы хотите сохранить несколько профилей одной и той же программы).
Примечание: Мы рекомендуем Вам сохранять результаты профилирования, получение которых заняло много времени, на тот случай, если у Вас вдруг возникнет желание снова взглянуть на эти данные.
Подготовка к получению профиля.
Примеры первой главы были небольшими и достаточно простыми, они были созданы для того, чтобы в общих чертах показать процесс профилирования. Основной задачей, поставленной в первой главе было скорее совершенствование программы prime, чем поиск «узких мест» данной программы.
На самом же деле необходимость использования профилировщика возникает в гораздо большей степени при написании программ большого размера, чем в случае, когда программы малы, так как сначала необходимо выявить «узкие места» программы, а уже потом пытаться понять то, каким образом можно усовершенствовать каждое из них. Вследствие ряда причин найти «узкие места» легче, чем придумать как с ними лучше поступить.
Перед тем, как профилировать Вашу программу, преобразуйте ее исходный текст для того, чтобы извлечь максимальную пользу из полученных статистических данных. Скомпилируйте Вашу программу (независимо от того внесли Вы в нее какие-либо изменения или нет) в режиме с включенной отладочной информацией. Затем установите маркеры, которые укажут профилировщику в каких местах и какие данные собирать.
Преобразование текста Вашей программы.
Первое, что вам необходимо сделать — это привести вашу программу к такому виду, который позволит вам понять, какие именно данные вам необходимо получить в результате профилирования. Например, если вы разрабатываете интерактивную программу, в которой часто происходит выполнение операторов ввода с клавиатуры, то вам совсем неинтересно будет узнать о том, что большая часть времени выполнения вашей программы тратиться на ожидание того момента, когда пользователь нажмет на какую-либо клавишу.
Вот некоторые основные технические приемы, используемые при поиске «узких мест» в больших программах:
* Задавайте вашим программам достаточно большие наборы входных данных, для получения наиболее информативных профилей.
Если вы попытаетесь профилировать программу поиска подстрок, подавая ей на вход файл, состоящий из трех строчек, то вы не сможете почерпнуть многого из полученных в результате этого данных. Точно также поиск коротких подстрок, входящих почти в каждую из строк файла (с общим числом строк равным 10000), даст профиль совершенно непохожий на тот, который получился бы в случае поиска длинной подстроки, встречающейся в данном файле один единственный раз.
Примечание: Выбор входных данных для вашей программы это очень важный момент на который следует обратить особое внимание.