Система Turbo Profiler фирмы Borland - Автор неизвестен 17 стр.


Delay(1000);

highway80;

Writeln('back in main');

delay(100);

Writeln('Leaving main');

End.

Задание в качестве «областей» всех подпрограмм в рассматриваемом модуле ведет к образованию четырех переменных для подсчета времени и четырех переменных для подсчета количества вызовов.

Рис. 2.1 Переменные для подсчета времени выполнения и числа вызовов подпрограмм для PTOLL/PTOLLPAS.

Воображаемые пункты сбора подорожной пошлины.

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

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

Рассмотрим, каким образом происходит сбор временной и количественной информации для типичной программы, написанной на Паскале или С.

Перед тем, как Вы попадете в функцию main, выполняется стартовый код С. Это еще пока ничейная территория. Каждый импульс таймера, происходящий во время прохождения данного участка, не учитывается, за исключением того случая, когда Вы явно помечаете стартовый код как «область».

Как только Вы преодолели маркер «области» (пункт сбора пошлины), которым помечена функция main переменная, отвечающая за подсчет числа вызовов main, автоматически увеличивается на единицу и каждый импульс таймера, происходящий с момента входа в main до вызова route66, увеличивает значение переменной, в которой учитывается время выполнения функции main.

На следующем этапе выполнения main вызывает функцию route66 и Вы попадаете на новый участок дороги. В момент перехода через маркер (пункт сбора пошлины), которым отмечена функция route66, происходит несколько вещей:

* Текущей «областью» начинает считаться route66;

* Отправляются в стек переменные, в которых накапливаются данные для вызывающей функции (в данном случае — функции main);

* Переменная, в которой подсчитывается количество вызовов route66, увеличивается на единицу.

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

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

Переменная, накапливающая количество обращений к вызывающей функции в этот момент не изменяется. Тем не менее, каждый импульс таймера, происходящий с этого момента до вызова highway80 добавляется, как к переменной, в которой накапливается время работы функции main, так и к переменной, в которой накапливается время выполнения всей программы. Для того, чтобы проверить этот факт, попробуйте убрать маркер «области», отмечающий route66 и затем сравнить данные, которые получаются в после этого, c профилем для случая, когда маркер установлен. Вы должны заметить, что общее время выполнения осталось тем же. Время же выполнения main должно увеличиться как раз на столько, сколько раньше требовалось для выполнения route 66.

Определение затрат времени на вызов подпрограмм.

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

(Также вы можете получить информацию такого рода при работе профилировщика в пассивном режиме анализа, обсуждаемом в Главе 3). А теперь, поместите курсор на первую строку route66, затем выберите команду Operation (Работа) в локальном меню окна Module (Модуль), для того, чтобы открыть блок диалога Area Options (Параметры «области»), установите Operation (Работа) в состояние Disable (Отключить), нажмите клавишу Enter.

Когда вы отключаете сбор статистики при входе в route66, при возврате из этой подпрограммы, сбор данных автоматически не возобновляется. Вы должны установить маркер «области» на закрывающую фигурную скобку функции route66, и снова установить параметр Operation (Работа) для данного маркера «области» в состояние Enable.

Кто расплачивается за циклы.

Метафора пунктов сбора подорожной пошлины помогает объяснить почему не изменяется текущая «область» после перехода маркера «области» с последующим возвратом назад (происходящим в результате выполнения оператора goto или цикла) по адресу, предшествующему этому маркеру, хотя, c лексической точки зрения, вы находитесь вне зоны действия маркера, вы еще не встретили на своем пути какой-либо маркер. И поэтому каждый генерируемый импульс таймера продолжает ассоциироваться с последним пройденным маркером.

/* Copyright (c) 1990, Borland International */

#include <stdio.h>

#include <dos.h> /* contains prototype for delay() */

main()

{

printf(«Entering main\n»);

lostintown();

delay(1000);

printf(«Leaving main\n\n»);

delay(1000);

}

lostintown()

{

int i;

printf(«Looking for highway…\n»);

delay(100);

for (i=0; i<10; i++)

Назад Дальше