ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
Часть 2 ВВЕДЕНИЕ Система Turbo Profiler фирмы Borland - это как раз то, чего не хватает в Вашем процессе создания программного обеспечения. Если ваша программа уже делает то, что Вам требуется, то система Turbo Profiler поможет Вам повысить ее скорость и эффективность. Итак, что же из себя представляет профилировщик? Профилиров- щики (называемые также анализаторами процесса выполнения про- грамм) - это программные средства, позволяющие получить ряд коли- чественных данных о процессе выполнения Вашей программы и на ос- новании этих данных выявить в ней "узкие места", отрицательно сказывающиеся на эффективности ее работы. Профилировщик позволяет получить следующую информацию о процессе выполнения программы: * как и на что расходуется время работы программы; * сколько раз выполняется данная строка программы; * сколько раз и какими модулями вызывается данный модуль про- граммы; * к каким файлам обращается ваша программа и сколько времени она на это тратит. Профилировщики так же собирают информацию о использовании критических ресурсов компьютера, к которым относятся: * процессорное время; * обращения к диску; * ввод с клавиатуры; * вывод на печать; * использование прерываний. Система Turbo Profiler контролирует каждый шаг выполнения программы и предоставляет подробные статистические сведения о всех этапах ее работы, что позволяет Вам доводить Ваши программы до совершенства. Обнажая внутренний механизм работы программы и вскрывая сущность наиболее сложных операций (что достигается за счет широких возможностей профилировщика начиная от подсчета вре- мени и количества выполнений операторов и заканчивая контролем за вызовами прерываний и обращениями к файлам), система Turbo Profiler помогает Вам отшлифовать ваш код и увеличить быстродей- ствие Ваших программ. Система Turbo Profiler превосходит другие имеющиеся на рынке профилировщики как по мощности, так и по простоте использования, и характеризуется следующими основными чертами: * Профилирование в интерактивном режиме, обеспечивающее быст- рое выявление непроизводительных участков программы. * Профилирование программ любого размера, выполняющихся под управлением DOS. * Профилирование программ, написанных на языках Turbo Pascal, Turbo C++, Turbo C и Turbo Assembler, а так же программ, скомпилированных с помощью Microsoft C и MASM. * Удобный и простой многооконный интерфейс с перекрывающимися окнами, возможностью использования мыши и контекстно-зависи- мой помощью. * Подсчет времени выполнения и количества вызовов как для под- программ, так и для отдельных операторов. * Отслеживание всех путей вызова для каждой подпрограммы. * Анализ частоты вызова подпрограммы с просмотром полного сте- ка вызова для каждого случая. * Контроль работы с файлами DOS, осуществляемый в окне Files (Файлы) и включающий в себя учет обращений к файлам и време- ни, затраченного на открытие, закрытие, чтение и запись фай- лов. Для каждого файла подсчитывается число байт, записанных в файл и прочитанных из него. * Возможность выборочного контроля работы программы с прерыва- ниями. Контроль всех прерываний от видеоадаптеров, клавиату- ры, дисководов, мыши, а так же нестандартных прерываний. Ве- дение полного протокола или просто учет частоты обращения. Ведение списка вызовов прерываний, в котором они обозначены символическими именами, что позволяет быстро найти нужное прерывание. * Поддержка полной трассировки оверлеев для языков Turbo Pascal и Turbo С. * Профилирование на виртуальной машине в системе с 386 процес- сором не занимает оперативную память, полностью отдавая ее в распоряжение Вашей программы. * Поддержка удаленного профилирования. * Поддержка работы с программами, написанными на языках С и ассемблер, формат исполнимых файлов которых совместимы по своему формату с системой Codeview. * Профилирование любой программы, полученной в результате ра- боты любого компилятора, если она сопровождается стандартным MAP-файлом в формате Microsoft. Реализуя возможности, отсутствующие в оптимизаторах, Turbo Profiler выявляет участки программы на выполнение которых затра- чивается большое количество времени, показывая тем самым в каком месте необходимо внести улучшения или изменить алгоритм работы. Отличие профилирования от оптимизации Оптимизатор делает работу программы более быстрой за счет замены долго работающих команд на эквивалентные, но требующие меньших затрат времени. Но оптимизация не может значительно по- мочь в случае, когда программа неэффективна по своей сути. Профилировщик помогает Вам обнаружить наименее эффективные участки вашего кода и понять какие, из алгоритмов нуждаются в мо- дификации или полной переработке. Исследования показывают, что наибольший эффект, при попытке улучшить рабочие характеристики программы, достигается скорее за счет изменения алгоритмов и структур данных, чем за счет оптимизации небольших участков кода, полученного в результате компиляции. Пытаться найти в Вашей про- грамме критические (в смысле производительности) места не пользу- ясь при этом профилировщиком.- это все равно, что пытаться найти в ней ошибки без помощи отладчика. Turbo Profiler экономит как ваше время, так и Ваши усилия. УСЛОВИЯ РАБОТЫ Turbo Profiler работает на компьютерах семейства IBM PC, включая XT, AT, PS/2 и все полностью IBM-совместимые компьютеры. Для его работы требуется операционная система DOS версии 2.0 или более высокой, а так же не менее 384К оперативной памяти и любой дисплей, строка которого содержит 80 символов. Мы рекомендуем пользоваться жестким диском, хотя возможна работа на компьютере, имеющем два дисковода для гибких дисков. Математический сопроцес- сор 80x87 для работы.системы Turbo Profiler не требуется. УСТАНОВКА СИСТЕМЫ TURBO PROFILER Для того, чтобы установить Turbo Profiler на Вашей вычисли- тельной системе, необходимо запустить инсталляционную программу INSTALL.EXE, находящуюся на Ваших дистрибутивных дискетах. Эта программа автоматически скопирует файлы с дистрибутивных дискет на ваш жесткий диск. Для этого нужно только вставить инсталляци- онную дискету в дисковод А, набрать на клавиатуре A:INSTALL, и нажать клавишу ENTER. Затем необходимо следовать инструкциям, ко- торые появятся на Вашем экране. Дистрибутивные дискеты отформатированы как двухсторонние с двойной плотностью и могут быть прочитаны на компьютерах семейст- ва IBM PC и совместимых с ними. Перечень файлов, находящихся на Ваших дистрибутивных дискетах находится в файле README на инстал- ляционной дискете. Файл README Перед тем, как начать работу с системой Turbo Profiler, оз- накомьтесь с содержимым файла README, который находится на инс- талляционной дискете. Этот файл содержит самые последние сведе- ния, которые могут отсутствовать в данном руководстве. Также он включает в себя перечень всех файлов, находящихся на дистрибутив- ных дискетах с кратким описанием каждого из них. Для того, чтобы просмотреть файл README, вставьте инсталля- ционную дискету в дисковод А, переключитесь на работу с дисково- дом А; для этого необходимо набрать на клавиатуре А: и нажать клавишу ENTER, затем набрать README и еще раз нажать клавишу ENTER. Если Вы находитесь в файле README, то Вы можете переме- щаться по тексту при помощи клавиш "стрелка-вверх" и "стрелка- вниз", а для окончания просмотра файла нажать клавишу ESC. КРАТКОЕ СОДЕРЖАНИЕ "Введение" дает общее представление о том, что такое профи- лирование, описывает основные характеристики системы Turbo Profiler, и готовит Вас к запуску системы Turbo Profiler на Вашем компьютере. Глава 1, "Пример работы с профилировщиком", это учебная гла- ва в которой описан (типичный и в то же время достаточно простой) сеанс работы с профилировщиком. Эта глава начинается с получения профиля программы, позволяющего понять, что происходит во время ее выполнения, затем последовательно проводит Вас через интерпре- тацию полученного профиля программы, модификацию и совершенство- вание программы на основе анализа профиля, и получение последую- щих профилей для оценки эффективности каждого изменения, внесен- ного в программу. Глава 2, "Внутри профилировщика", в которой наглядно объяс- няется каким образом профилировщик получает количественные и вре- менные характеристики процесса выполнения программы. Глава 3, "Стратегия профилирования", содержит общие принци- пы, а также описание некоторых приемов профилирования, которые необходимо знать для успешной работы с профилировщиком. Глава 4, "Среда системы Turbo Profiler", подробно рассказы- вает о каждом пункте меню и каждом параметре среды системы Turbo Profiler. Приложение А, "Параметры командной строки системы Turbo Profiler", в нем перечислены все параметры командной строки сис- темы Turbo Profiler и объяснено назначение каждого из параметров. Приложение В, "Настройка системы Turbo Profiler", объясняет как пользоваться TFINST для того чтобы изменить конфигурацию сис- темы Turbo Profiler, задаваемую по умолчанию. Приложение С, "Удаленное профилирование", описывает как про- исходит профилирование с использованием двух компьютеров, на од- ном из которых исполняется ваша программа, а на другом Turbo Profiler. Приложение D, "Виртуальное профилирование с использованием процессора 80386", описывает, как запустить Turbo Profiler таким образом, чтобы он пользовался только расширяемой памятью процес- сора 80386, оставляя все 640К основной памяти для Вашей програм- мы. Приложение С, "Приглашения и сообщения об ошибках", где пе- речислены все приглашения и сообщения об ошибках, которые могут появиться в процессе Вашей работы с системой Turbo Profiler, и даны рекомендации каким образом на них нужно реагировать. Замечания по терминологии Для удобства и краткости в данном руководстве мы используем термины "модуль", "подпрограмма" и "аргумент" в более широком смысле чем обычно. "модуль" Модуль в данном руководстве это то, что обычно называется модулем в С но так же этим словом мы называем Паскалев- ский UNIT. "подпрограмма" Аналогично предыдущему термин "подпрограмма" в данном руко- водстве относится как к функ- циям С, так и к подпрограммам Паскаля, которые включают в себя функции, процедуры и ме- тоды объекта. В С функция мо- жет возвращать некоторое зна- чение (как это делают функции в Паскале), а может и не воз- вращать никакого значения (аналогично процедурам в Пас- кале).(Если функция в С не возвращает значение, то она называется функцией типа void) Мы используем термин подпрограмма для обозначения как функций С, так и процедур и функций Паскаля. "аргумент" И, наконец, термин "аргумент" в данном руководстве исполь- зуется в качестве эквивалента термина параметр. Он применя- ется для обозначения аргумен- тов командной строки, исполь- зуемых при вызове программ из DOS, с таким же успехом как и для обозначения аргументов, передаваемых подпрограмме. ГЛАВА 1. ПРИМЕР РАБОТЫ С ПРОФИЛИРОВЩИКОМ Профилирование - это одна из еще пока недооцениваемых, но очень полезных и даже жизненно необходимых частей процесса созда- ния качественного программного обеспечения. Обзоры показывают, что, на самом деле, только незначительная часть профессиональных программистов использует профилировщики для улучшения своих про- грамм. Другие же исследования говорят о том, что в большинстве случаев даже опытные программисты неправильно указывают критиче- ские участки ("узкие места") в своих программах. Каковы же преимущества использования описываемого нами ору- дия? Во-первых профилирование Ваших программ может повысить их производительность. Во-вторых профилирование может усилить вашу способность создания эффективных программ. И, наконец, профилиро- вание, как и отладка, может стать неотъемлемым элементом цикла создания программного обеспечения. В этой главе мы продемонстрируем Вам пример того, каким об- разом можно извлечь пользу из применения профилировщика, и как в дальнейшем профилирование может сэкономить Вам часы во время по- иска строк программы, расточительно использующих ресурсы компью- тера. Вы научитесь применять профилировщик для того чтобы: * обнаруживать где и на что ваша программа расходует время; * создавать аннотированный листинг исходного текста Вашей про- граммы и статистический отчет о профилировании; * запоминать статистические данные, полученные в результате профилирования и затем, после перерыва, возвращаться к рабо- те с этими данными; * анализировать статистику профилирования и исходный текст Ва- шей программы, находящиеся, в соседних окнах. Примечание: Примеры этой главы основаны на колонке Джо- на Бентли в журнале Communications of the ACM (июль 1987), которая называется "Жемчужины программирования" ("Programming Pearls"). Примечание: Все примеры были опробованы на машине с 286 процессором и видеоадаптером Hercules. Примеры в данной главе основываются на поиске и распечатке всех простых чисел, находящихся в диапазоне от 1 до 1000. Вспом- ним, что число является простым если оно делится только на 1 и само на себя, очевидно, что оно должно быть нечетным, так как лю- бое четное число делится на 2 и, следовательно, не является про- стым. Для того чтобы определить, является ли данное число про- стым, необходимо проверить не является ли какое либо простое чис- ло, меньшее данного, его делителем, а так же проверить не делится ли рассматриваемое число на какое -нибудь целое, большее двух первых простых чисел 2 и 3. Целью профилирования программ-примеров является ускорение процесса нахождения и печати простых чисел. Проработав эти приме- ры Вы научитесь использовать Turbo Profiler для определения эф- фективности структуры программы каждого из примеров. Первой программой, которую мы рассмотрим, будет PRIME0. Как только Вы отпрофилируете ее и поймете в каких местах необходимо изменить ее текст, Вам необходимо переходить к следующему шагу - загрузке и профилированию PRIME1. За исключением PRIME1, каждая из программ, рассматриваемых в данной главе (PRIME2, PRIME3, PRIME4, PRIME5 и PRIME6) является модификацией предыдущей. Важное замечание: Информация для пользователей Паскаля. Программы PRIMEn.* написаны на Turbo C. Для пользовате- лей Паскаля имеются аналоги этих программ PRIMEnPA.* которые могут использоваться для упражнений во время чтения данной главы. Каждое обсуждение профилирования программы, написанной на С сопровождается комментарием, отражающим отличия в случае профилирования Паскалевской программы. Убедитесь, что все файлы с примерами (PRIMEn.C и PRIMEn.EXE или PRIMEnPA.PAS и PRIMEnPA.EXE) находятся в Вашей текущей дирек- тории. Для каждого из описываемых примеров имеются как исходные файлы, так и выполнимые файлы, поскольку для анализирования про- граммы Turbo Profiler требуются и те и другие. Каждый из примеров был скомпилирован с полной символической информацией, так как эта информация необходима для профилирования. Для того чтобы обеспечить наличие полной символической ин- формации для Ваших программ, необходимо при их компиляции задать следующие параметры: Turbo C++: При работе в интегрированной среде, необходимо выбрать в меню Options| Full Menus (Параметры| Полный набор меню) затем открыть блок диалога отладчика (для этого надо выбрать Options| Debugger (Параметры| Отладчик)), и установить Source Debugging (Отладка на уровне исходного кода) в значение Standalone (Самостоятельный отладчик). При компиляции с использо- ванием командной строки необходимо задавать параметр -v. Turbo C: Если Вы компилируете в интегрированной среде, то необходимо перед компиляцией программы выбрать Standalone (Само- стоятельный отладчик) в параметрах отладчика Debug| Source Debugging (Отладчик| Отладка на уровне исходного текста). При компиляции с использованием командной строки необходимо задавать параметр -v. Turbo Pascal: Если Вы компилируете в интегрированной среде, необходимо установить пункты меню Options|Debug Information (Па- раметры|Отладочная информация) и Debug|Stand-Alone Debugging (От- ладка| Самостоятельный отладчик) в состояние On. При компиляции с помощью командной строки необходимо использовать параметр /v. Turbo Assembler: Необходимо использовать параметр /zi, затем строить загрузочный модуль при помощи TLINK, задавая при этом па- раметр /v. Информация для пользователей 80x87. Поскольку Turbo Profiler способен использовать возможности математического сопроцессора, в том случае если сопроцессор уста- новлен на Вашем компьютере, и Вы хотите получить статистические данные, соответствующие изложенным в настоящем руководстве, то Вам необходимо временно запретить использование сопроцессора (в противном случае полученные вами результаты будут значительно от- личаться от приведенных в этом тексте). Для того чтобы Turbo Profiler не пользовался возможностями сопроцессора достаточно пе- ред началом работы с профилировщиком выполнить команду DOS SET 87=N. Но даже в этом случае полученные статистические данные мо- гут сильно отличаться от изложенных в данном руководстве, из-за несовпадения технических характеристик компьютеров таких, напри- мер, как быстродействие процессора. Профилирование программы (PRIME0) Процесс профилирования и корректировки программы состоит из следующих четырех этапов: 1. Загрузка программы перед ее профилированием. 2. Сбор данных во время выполнения программы. 3. Анализ полученных данных. 4. Модификация программы и ее повторная компиляция. После внесения изменений в программу необходимо повторить выполнение пунктов с 1 по 3 для того, чтобы посмотреть как повли- яли эти изменения на поведение программы в процессе исполнения. Программа PRIME0 использует алгоритм Евклида для нахождения простых чисел. Как только простое число найдено, оно сразу же за- писывается в массив primes и для того, чтобы определить являются ли последующие числа простыми, делается попытка поделить их на числа, уже записанные в массив primes. Загрузите PRIME0 в систему Turbo Profiler, набрав на клавиа- туре Turbo Profiler PRIME0 и нажав клавишу ENTER. Примечание: Вы можете закончить работу с профилировщи- ком в любой момент. Для этого необходимо выбрать в меню последовательность File|Quit (Файл|Выход) или нажать комбинацию Alt-X. Важное замечание: Информация для пользователей Паскаля. Если Вы хотите профилировать Паскалевскую версию PRIME0.C, то убедитесь, что файлы PRIME0PA.PAS и PRIME0PA.EXE находятся в Вашей текущей директории после чего наберите на клавиатуре TPROF PRIME0PA и нажмите Enter. В начале работы Профилировщика откроются два окна: Module (Модуль) (в котором находится исходный текст PRIME0) и Execution Profile (Профиль выполнения) (в котором, после того как Вы запу- стите программу PRIME0, будет отображена статистика процесса ее выполнения). Рис.1.1 Turbo Profiler с загруженной в него программой PRIME0 Окно Module (Модуль) и окно Execution Profile (Профиль вы- полнения) относятся к шагам 1 и 3 процесса профилирования. Окно Module (Модуль) используется для того, чтобы помечать участки программы, которые необходимо профилировать. После того как Вы запустите программу, в окне Execution Profile (Профиль выполне- ния) отображается информация, необходимая для анализа ее работы. Установка параметров профилирования. Перед началом профилирования программы необходимо пометить в ней интересующие Вас "области". "Область" - это участок программы для которого Вы хотели бы получить статистические данные. "Обла- стью" может быть одна строка, один оператор (например оператор цикла) или вся программа целиком. Во время первого сеанса профи- лирования Вам потребуется собрать более обширную информацию о "областях" чем та, которая задается параметрами системы Turbo Profiler по умолчанию. Для того, чтобы проанализировать небольшое количество корот- ких подпрограмм (таких, как prime и main в данной программе), Вы должны знать сколько раз выполняется каждая их строка и сколько времени занимает ее выполнение. Для того, чтобы получить эту ин- формацию, Вы должны пометить каждую строку этой программы как "область". 1. Нажмите Alt-F10, для того чтобы активировать локальное меню окна Module (Модуль). 2. Выберите в этом меню Add Areas (Добавить "области"). Вам бу- дет предложен для выбора список возможных границ "области". 3. Выберите Every Line in Module (Каждая строка в модуле). В результате этого маркеры "области" будут установлены для каждой строки программы и курсор вернется в окно Module (Мо- дуль). Обратите внимание на то, что в результате выполнения пере- численных операций все выполнимые строки программы оказались по- меченными маркером =>. Сбор статистических данных Итак, в настоящий момент Вы готовы к проведению второго эта- па профилирования. Нажмите клавишу F9 для запуска PRIME0 под кон- тролем Turbo Profiler. Программа выдаст на экран пользователя простые числа, находящиеся в диапазоне от 1 до 1000. Когда выпол- нение программы завершится, просмотрите информацию, появившуюся в окне Execution Profile (Профиль выполнения). Это и есть статисти- ка процесса выполнения Вашей программы. Распахните окно Execution Profile (Профиль выполнения), на- жав клавишу F5 или выбрав Zoom (Распахнуть) из меню Window (Ок- но). После чего окно Execution Profile (Профиль выполнения) будет выглядеть следующим образом: Рис.1.2 Статистика процесса выполнения программы PRIME0 Верхняя панель окна Execution Profile (Профиль выполнения) показывает общее время выполнения программы, сопровождаемое ин- формацией о данных, находящихся на нижней панели. В каждой строке нижней панели содержится четыре позиции: * название "области"; * количество секунд, затраченных на выполнение данной области; * процентное отношение этого времени к общему времени выполне- ния программы; * горизонтальная диаграмма, пропорциональная этому отношению. Строка вида #PRIME0#31 6.2655 sec 93% |============================ говорит о том, что тридцать первая строка программы PRIME0 выполнялась в течение 6.3 секунды, что составило 93% от времени выполнения всех помеченных "областей". Диаграмма для строки 31 автоматически занимает все отведенное для диаграммы место, так как на выполнение 31 строки затрачивается самое большое количест- во времени среди всех помеченных областей. Важное замечание: Информация для пользователей Паска- ля.В программе PRIME0PA, соответствующая строка имеет номер 42. Изображение статистики Также Вы можете просмотреть количественные данные о процессе выполнения Вашей программы. 1. Нажмите Alt-F10 для вызова меню окна Execution Profile (Профиль выполнения). 2. Выберите в этом меню команду Display (Изображение) Блок диалога для установки параметров изображения предостав- ляет пять способов изображения данных в окне Execution Profile (Профиль выполнения). Рис.1.3 Блок диалога задания параметров изображения * Time ("Время")задает изображение полного времени затра- ченного на выполнение каждой из помеченных "областей". (этот параметр задается по умолчанию) * Count ("Подсчет") задает изображение числа, показываю- щего сколько раз за время выполнения программы управле- ние передавалось помеченной "области". * Both ("И то, и другое") задает одновременный показ вре- мени выполнения и количества вызовов. * "Per Call" ("На один вызов") ведет к изображению сред- него времени затраченного на одно выполнение помеченной "области". * Longest ("Самое большое") ведет к показу максимального времени затраченного на выполнение данной "области". 3. Выберите Counts (Подсчет) в графе Display (Изображение) в рассматриваемом блоке диалога.(Сделайте это при помощи мыши, или используя клавиши управления курсором перейдите к этому пункту и нажмите клавишу ENTER, того же самого результата можно достичь простым нажатием клавиши С.) 4. Выберите ОК (или нажмите ENTER). Теперь окно Execution Profile (Профиль выполнения) показыва- ет не временную, а количественную статистику выполнения программы PRIME0, как показано на следующем рисунке. Рис.1.4 Количественная статистика в окне профиля программы: Эти изображенные на экране данные говорят о том, что наибо- лее часто в программе PRIME0 выполняется строка 22. (Соответству- ющая строка в программе PRIME0PA имеет номер 31.) При желании Вы можете посмотреть количественную и временную статистику одновременно. Для этого нужно снова вызвать блок диа- лога Display Options (Параметры изображения) (нажав для этого Alt-F10 и выбрав Display (Изображение) или нажав Ctrl-D). Выберите Both ("И то, и другое") в столбце Display (Изобра- жение), затем выберите ОК или нажмите ENTER. ( Для того, чтобы это сделать надо выбрать Both ("И то, и другое") при помощи мыши, или перейти к Both ("И то, и другое") при помощи клавиш управле- ния курсором и нажать ENTER, также можно просто нажать клавишу В ) Теперь окно Execution Profile (Профиль выполнения) выглядит следующим образом: Рис.1.5 Временная и количественная статистика в окне Execution Profile (Профиль выполнения) Если в окне Execution Profile (Профиль выполнения) временная и количественная статистика изображаются одновременно, то для каждой помеченной "области" первое число, относящееся к этой "об- ласти"- это количество выполнений данной "области", а второе чис- ло- это время, затраченное на выполнение данной "области". Рису- нок 1.5 показывает, что "область" PRIME0#22 (строка 22 в програм- ме PRIME0) выполнялась 15 122 раза, что заняло в общей сложности 0.31 секунды. Печать текстов программ и статистики В этом разделе Вы научитесь печатать две вещи: 1. Листинг исходного текста профилируемой программы, находящей- ся в окне Module (Модуль) с количественной и временной ста- тистикой, сопровождающей каждую помеченную "область". 2. Статистику профилирования, изображенную в окне Execution Profile (Профиль выполнения). Печать листинга профилируемой программы. Перед тем как вывести в файл листинг профилируемой програм- мы, содержащий временную и количественную статистику, Вы должны задать соответствующие параметры печати: 1. Выберите команду Print|Options (Печать|Параметры). 2. В блоке диалога Printing Options (Параметры печати) выберите селективную кнопку File (Файл) для этого нажимайте TAB до тех пор пока не активируются селективные кнопки, затем, при помощи клавиши "стрелка вниз", выберите параметр File (Файл)). 3. При помощи клавиши TAB активируйте блок ввода Destination File (Файл назначения) и наберите на клавиатуре PRIME0SC.LST 4. Выберите ASCII для того чтобы пользоваться стандартной коди- ровкой ASCII, а не расширенным набором символов IBM. 5. Bыберите ОК или нажмите (ENTER). Теперь курсор находится в активном окне Execution Profile (Профиль выполнения). Для того, чтобы вывести листинг в файл выберите в меню ко- манду Print|Module (Напечатать|Модуль). В блоке диалога PIck a Module (Выбрать модуль) при помощи клавиши "стрелка вниз" выбери- те название модуля PRIME0, затем нажмите ENTER (или выберите ОК). Вы можете выйти в DOS (не выходя из системы Turbo Profiler), чтобы просмотреть файл PRIME0SC.LST, который должен быть выведен в текущую директорию. Выберите в меню команду File|Dos shell (Файл|Оболочка DOS) и наберите на клавиатуре TYPE PRIME0SC.LST Если Вы профилируете программу PRIME0, написанную на Turbo C, Вы должны увидеть на экране следующее: /* Copyright (c) 1990, Borland International */ /* Программа генерации простых чисел при помощи алгоритма Эвкли- да */ int primes[1000]; #define MAXPRIMES 1000 main() { int j; int lastprime, curprime; primes[0] = 2; primes[1] = 3; lastprime = 1; curprime = 3; printf("prime %d = %d\n", 0, primes[0]); printf("prime %d = %d\n", 1, primes[1]); while(curprime < MAXPRIMES) { for(j = 0; j <= lastprime; j++) if((curprime % primes[j]) == 0) { curprime += 2; break; } if(j <= lastprime) continue; lastprime++; printf("prime %d = %d\n", lastprime, curprime); primes[lastprime] = curprime; curprime += 2; } } Примечание: времена выполнения "областей", фигурирующие в Вашем файле могут отличаться от приведенных здесь из-за различий между Вашим компьютером и тем, на котором были получены изобра- женные результаты. Иметь этот листинг Вашей отпрофилированной программы очень полезно, так как он остается после сеанса работы с профилировщи- ком и содержит количественную и временную статистику для каждой помеченной "области" Вашей программы. Теперь наберите на клавиатуре EXIT и нажмите клавишу ENTER для того, чтобы вернуться в среду системы Turbo Profiler. Отчет о статистике профилирования. При необходимости Вы можете вывести содержимое окна Execution Profile (Профиль выполнения) в файл или на принтер. 1. Снова выберите Print|Options (Принтер|Параметры). 2. Выберите селективную кнопку Printer (Принтер). 3. Выберите Graphics (Графика) для того, чтобы включить в выда- чу псевдографические символы IBM (Если ваш принтер не под- держивает псевдографические символы, пропустите этот шаг и переходите к шагу 4.) 4. Нажмите ENTER или (выберите ОК). 5. Выберите Print|Statistics (Печать|Статистика). В результате выполнения вышеперечисленных действий, Вы полу- чите выдачу, в которой будет отражен каждый шаг вашего сеанса профилирования (получение профиля, модификация программы, повтор- ная компиляция (рекомпиляция), повторное получение профиля (ре- профилирование)) на пути поиска наиболее совершенного и эффектив- ного текста Вашей программы. Сохранение и восстановление статистических данных. Перед тем как продолжить сеанс профилирования, научимся за- писывать в файл статистические данные о процессе выполнения про- граммы PRIME0, для того, чтобы иметь возможность в любой момент покинуть среду системы Turbo Profiler, не потеряв при этом необ- ходимые данные. Также мы научим Вас считывать эти данные в среду профилировщика при последующих сеансах работы. Выберите команду Statistics| Save (Статистика| Сохранить) для сохранения статистики профилирования в файле с расширением .TFS (Turbo Profiler Statistics (Статистические данные системы Turbo Profiler)). Так как в окне Module (Модуль) находится PRIME0, то блок ввода File Name (Имя файла) по умолчанию предла- гает PRIME0.TFS для названия файла в котором будет хранится ста- тистика. Для того,чтобы создать этот файл выберите ОК. Все статистические данные текущего сеанса профилирования PRIME0 теперь сохранены в файле PRIME0.TFS, находящемся в текущей директории, следовательно теперь Вы можете в любой момент поки- нуть среду профилировщика, не потеряв при этом полученные данные. Для того,чтобы просмотреть статистику, загрузите PRIME0 в профи- лировщик и выберите в меню команду Statistics|Restore (Статисти- ка|Восстановить). Как и в предыдущий раз, в блоке ввода File Name (Имя файла) по умолчанию будет задан файл PRIME0.TFS. Нажмите ENTER для перехода в блок списка Files (Файлы), выберите в нем PRIME0.TFS и, затем, выберите ОК для восстановления статистиче- ских данных из этого файла. Анализ статистики. В этом разделе Вы научитесь анализировать статистику, нахо- дящуюся в окне Execution Profile (Профиль выполнения), для того, чтобы на основании этой статистики вносить в вашу программу улуч- шения. Для начала еще раз посмотрим на временную и количественную статистику, находящуюся в окне Execution Profile (Профиль выпол- нения). Распахните окно Execution Profile (Профиль выполнения (Выберите команду Zoom (Распахнуть) из меню Window (Окно) или на- жмите F5) и посмотрите на статистику для строк 22 и 31 (операторы if и printf). Важное замечание: Пользователям Паскаля. В PRIME0PA им соответствуют строки 31 (if) и 42 (Writeln). Из полученного профиля мы можем почерпнуть много полезных сведений. Например, легко заметить, что строка 22 в PRIME0 выпол- няется гораздо чаще чем любой другой оператор. Вполне понятно, что строка 22 выполняется 15 122 раза, так как в этой строке про- исходит проверка каждого числа в диапазоне от 4 до 1000 на дели- мость этого числа на элементы массива primes, проверка происходит до тех пор пока либо после деления остаток станет равным 0, либо массив primes будет исчерпан. Так же можно видеть, что строка 31 (оператор printf) отнимает большую часть времени выполнения про- граммы. Примечание: в программе PRIME5 содержится модифицированный вариант оператора printf, (пользователям Паскаля предназначена программа PRIME5PA с оператором CRT) Одновременный просмотр исходного текста и статистики. Данные в окне Execution Profile (Профиль выполнения) показы- вают, что в строке 22 программа выполняет большую работу, чем нам необходимо. Но полную картину того, что происходит во время вы- полнения программы можно получить лишь при одновременном рассмот- рении временной и количественной статистики с исходным текстом программы. Вам необходимо сопоставить временные и количественные дан- ные, находящиеся в окне Execution Profile (Профиль выполнения) с соответствующими строками исходного текста программы, находящего- ся в окне Module (Модуль). Вот один из способов одновременного получения на экране дис- плея исходного текста и статистики профилирования: 1. Изменим размеры и положение окна Execution Profile (Профиль выполнения) так, чтобы оно заняло правую половину вашего эк- рана. Для этого нужно выбрать в меню команду Window|Size/Move (Окно|Размеры/Положение) или нажать Ctrl- F5. 2. Следуйте указаниям, находящимся в строке состояния для того, чтобы: а. Изменить размеры окна так, чтобы оно занимало весь эк- ран в высоту и половину экрана в ширину. в. Передвинуть полученное окно вправо. После того как шаги а и в будут проделаны, нажмите клавишу ENTER. 3. Активируйте окно Module (Модуль), нажав для этого клавишу F6, затем измените его размеры и расположение так, чтобы оно заняло левую половину экрана. 4. Снова вернитесь в окно Execution Profile (Профиль выполне- ния) (нажав для этого клавишу F6). Мышь: Изменение размеров окна с помощью мыши происходит посредством перемещения по экрану маркера измене- ния размера, находящегося в нижнем правом углу. Для того, чтобы переместить окно, необходимо заце- пить заголовок этого окна или верхнюю или левую часть двойной рамки, ограничивающей окно и подтя- нуть окно в нужное место. Между окном Execution Profile (Профиль выполнения) и окном Module (Модуль) автоматически поддерживается связь, поэтому когда Вы перемещаетесь по исходному тексту программы, содержимое окна Execution Profile (Профиль выполнения) все время соответствует тому участку программы на котором Вы находитесь в данный момент. Для того, чтобы посмотреть этот механизм в действии необходимо сделать следующее : 1. Активируйте окно Execution Profile (Профиль выполнения) (на- жав для этого F6) и переместите световой маркер на первую строку (статистика для строки 31 программы PRIME0, или стро- ки 42 программы PRIME0PA). 2. Откройте локальное меню (нажмите для этого Alt-F10) и выбе- рите команду Module (Модуль) (или просто нажмите Ctrl-M). Профилировщик установит курсор в окне Module (Модуль) на строке 31. 3. При помощи клавиш управления курсором переместитесь на стро- ку 22 исходного текста программы (строка 31 в PRIME0PA). Эта строка занимает второе место по затратам времени в про- грамме PRIME0. Теперь в двух верхних строках окна Execution Profile (Профиль выполнения) находятся данные профилирования для рассматриваемого оператора if. 4. Переместите курсор в окне Module (Модуль) на строку 21 (на строку 29 в PRIME0PA) и посмотрите как изменилось содержимое окна Execution Profile (Профиль выполнения). Верхние строки в окне Execution Profile (Профиль выполнения) теперь содер- жат статистику для 21 строки программы. 5. Переместите курсор на строку 30 (на строку 42 в PRIME0PA) и посмотрите на данные в окне Execution Profile (Профиль вы- полнения). Наличие такой связи между двумя окнами облегчает нахождение участков Вашей программы, наиболее расточительно расходующих вре- мя ее выполнения. К тому же это может позволить избежать просмот- ра листинга профилирования (подобного рассмотренному ранее), в том случае если Вы предпочитаете анализировать данные, находящие- ся на экране компьютера. Сохранение конфигурации окон На данном этапе настал подходящий момент для того, чтобы за- помнить изменения, произведенные в конфигурации системы Turbo Profiler. Если Вы не сохраните текущее расположение и размеры окон, то при следующем сеансе работы с профилировщиком окна опять примут положение и размеры, задаваемые по умолчанию. 1. Выберите команду Options|Save Options (Параметры|Сохранить параметры). На экране появится блок диалога Save Configuration (Сохранение конфигурации). 2.По умолчанию триггерные кнопки Options (Параметры), находящиеся в данном блоке диалога уже установлены, и все установленные параметры (такие, например, как параметры изображения окна Execution Profile (Профиль выполнения)) записываются в файл конфигурации. 3. В блоке диалога Save Configuration (Сохранение конфигурации) при помощи клавиши TAB переместитесь в Layout (Компоновка) и нажмите клавишу "пробел". В результате этого текущая компо- новка окон "стык в стык" будет сохранена в файле конфигура- ции. 4. По умолчанию конфигурация записывается в файл TFCONFIG.TF, его имя уже установлено в блоке ввода Save To (Сохранить в). Выберите ОК, или нажмите ENTER, для того чтобы сохранить Ва- ши параметры в текущей директории в файле с этим названием. Как только Вы запускаете систему Turbo Profiler, она ищет файл TFCONFIG.TF, по умолчанию считается, что файл конфигурации имеет это имя. Как только профилировщик находит этот файл, он ав- томатически принимает конфигурацию, задаваемую параметрами,сохра- ненными в этом файле. Измерение эффективности работы "области" программы. Отношение общего времени, затраченного на работу данной "об- ласти" программы к числу передач управления на данную "область" является хорошей мерой для вычисления эффективности работы как одного оператора, так и всей программы. Для того, чтобы посмотреть это отношение для "областей", оп- ределенных в PRIME0, измените параметр изображения для окна Execution Profile (Профиль выполнения). Это можно сделать следую- щим образом: 1. Из локального меню окна Execution Profile (Профиль выполне- ния) выберите команду Display (Изображение). (Для этого не- обходимо нажать комбинацию клавиш Alt-F10.) 2. В появившемся блоке диалога выберите значение Per Call (На один вызов) параметра Display (Изображение). 3. Выберите ОК (или нажмите ENTER). Теперь Вы можете видеть, что строка 22 работает гораздо эф- фективнее строки 31 (в PRIME0PA строки 30 и 41 соответственно). Несмотря на то, что общее время, затраченное на выполнение данной строки, велико, поскольку эта строка выполняется большое количе- ство раз, среднее время ее выполнения составляет менее одной мил- лисекунды. Заметим, что среднее время выполнения строки 31 со- ставляет приблизительно 38 миллисекунд (в PRIME0PA среднее время выполнения строки 42 равно 28 миллисекундам). Данные, полученные профилировщиком показывают пути уменьше- ния времени работы PRIME0 и упрощения ее структуры. Можно выде- лить две стратегии улучшения программы: 1. Сокращение времени, затрачиваемого на выполнение операций ввода/вывода. 2. Изменение структуры операторов цикла на более эффективную и рациональную. Проблема ввода/вывода может быть частично решена за счет со- кращения оператора printf с его настоящего вида printf("prime #%d=%d\n", lastprime, curprime) до вида printf("%d\n", curprime). Информация для пользователей Паскаля: Вы можете приве- сти оператор Writeln к виду Writeln(CurPrime);. Только одно это простое изменение дает значительное уменьше- ние времени выполнения программы. Однако заметим, что Вы не може- те уменьшить количество обращений к оператору вывода (в данном примере на экран каждый раз будет выводиться 168 простых чисел). И, за исключением этого небольшого улучшения, Вы почти ничего не сможете сделать для ускорения работы PRIME0. Алгоритм этой про- граммы, который требует сохранения всех предыдущих результатов в массиве с последующим использованием их для деления, совершенен настолько, что дальнейшее его улучшение практически невозможно. (Заметим, что данный алгоритм не очень эффективен с точки зрения использования памяти, так как наличие массива требует резервиро- вания памяти, размеры которой должны позволить разместить все найденные простые числа. Из вышеизложенного следует ограничение на количество простых чисел, которые могут быть найдены данной программой, поскольку при некотором их количестве неизбежно про- изойдет переполнение оперативной памяти.) К счастью существует более оптимальный способ поиска простых чисел, но для того, чтобы им воспользоваться необходимо полностью изменить алгоритм, что и демонстрируется в следующем примере, в программе PRIME1. Модульная программа поиска простых чисел (PRIME1) Завершим рассмотрение PRIME0 и загрузим в окно Module (Мо- дуль) программу PRIME1, следующий вариант программы поиска про- стых чисел. Начнем изучение этой программы с простого просмотра ее текста. 1. Выберите команду File|Open (Файл|Открыть). 2. По умолчанию активируется блок ввода File Name (Имя файла), содержащий шаблон имени файла вида *.EXE. Нажмите ENTER. 3. В блоке списка Files (Файлы) переместите световой маркер на PRIME1.EXE (или PRIME1PA.EXE), используя для этого клавиши "стрелка вверх" и "стрелка вниз". 4. Нажмите ENTER. Система Turbo Profiler загрузит программу PRIME1 (PRIME1PA) в окно Module (Модуль). 5. Распахните окно Module (Модуль) (нажав для этого F5). Обра- тите внимание на то, что в строке 4 появилась подпрограмма prime (Prime). Сразу бросаются в глаза два отличия от предыдущего примера: * Во-первых, исчез массив primes. Данная программа не исполь- зует способ деления на меньшие простые числа, она просто со- держит в себе цикл, в котором делается попытка разделить рассматриваемое число на все нечетные числа, строго меньшие данного. Вначале результатом этого будет увеличение числа итераций по сравнению с предыдущим примером, но мы увидим, что в конечном итоге, после переработки данного примера, можно получить более рациональную и качественную программу. * Во-вторых проверка на то, является ли данное число простым, выделена в самостоятельную подпрограмму, которая вызывается из основной программы. Пометьте "области" в загруженной программе (выбрав для этого команду Add Areas|Every Line (Добавить "области"|Каждая строка) в локальном меню окна Module (Модуль)), нажмите ENTER, затем запу- стите PRIME1 (нажав F9) под управлением системы Turbo Profiler и ознакомьтесь с полученной статистикой. Затем выберите Display из локального меню окна Execution Profile (Профиль выполнения) для того, чтобы открыть блок диалога Display Options (Параметры изо- бражения) и привести кнопку Both в состояние On (Используется). Нажмите ENTER, затем распахните окно профиля (клавиша F5). Рис.1.6 Временная и количественная статистика. PRIME1. Вы можете заметить, что время выполнения немного уменьшилось (отчасти это произошло за счет того, что PRIME1 выдает на экран меньше информации чем PRIME0). Самым узким местом программы по- прежнему остается оператор printf (теперь находящийся в строке 21) (в PRIME1PA ему соответствует оператор Writeln в строке 24.) Отметим, что строка, в которой непосредственно проверяется является ли очередное число простым (строка 9 в PRIME0, строка 12 в PRIME0PA), теперь выполняется 78 022 раза вместо 15 122. На первый взгляд, этот факт выглядит впечатляюще, но нужно учесть, что в результате, общее время, затрачиваемое на выполнение данной строки, увеличится всего лишь примерно на 1 секунду, так как, в соответствии с ранее полученными данными, эта строка работает очень эффективно с точки зрения использования времени. Если принять во внимание, что цикл проверки числа выделен теперь в отдельную подпрограмму, то одним из очевидных путей по- вышения эффективности ее работы является сокращение вызовов дан- ной подпрограммы. Существует несколько путей сокращения количест- ва целых чисел, передаваемых данной подпрограмме для проверки. Чем больше чисел будет отсеяно на уровне основной программы, тем меньшее количество раз будет вызываться данная подпрограмма и тем быстрее будет выполняться вся программа в целом. В следующих не- скольких примерах мы продемонстрируем как на практике применяется вышеизложенная стратегия. Модификация программы и повторное профилирование. Бентли отмечает, что вместо проверки всех множителей из ин- тервала от 1 до n в операторе деления по модулю, достаточно огра- ничиться лишь числами, не превосходящими корня квадратного из рассматриваемого числа. Это и реализовано нами в программе PRIME2 (PRIME2PA). Загрузка программы PRIME2. Итак, продолжим наши упражнения. Для начала загрузим в окно Module (Модуль) программу PRIME2, следующую версию нашей програм- мы. В программе PRIME2 мы добавили использование подпрограммы root (Root), библиотечной подпрограммы вычисления квадратного корня, возвращающей в качестве результата целое число. Информация для пользователей Паскаля: Загрузите в окно программы PRIME1PA. Вам необходимо пометить каждую строку программы как "об- ласть". Вызовите локальное меню и выберите в нем команду Add Areas| Every Line in Module (Добавить "области"| Каждая строка в модуле), затем нажмите ENTER. Нажмите F9 для начала профилирования. На экране пользователя опять появятся все простые числа, находящиеся в диапазоне от 1 до 1000. Когда программа закончит свою работу, откройте блок диалога Display Options (Параметры изображения) (для этого выберите ко- манду Display (Изображение) из локального меню окна Execution Profile (Профиль выполнения)) и установите параметр Display в со- стояние Both ("И то, и другое"). Нажмите ОК. Несмотря на уменьше- ние количества обращений к строке 15 (c 78022 до 5288) и соответ- ственно сокращения общего времени, затрачиваемого на выполнение данной строки, полное время выполнения данной программы значи- тельно возросло. Объяснение данной особенности программы PRIME2 кроется в ис- пользовании новой подпрограммы root. Строка 7 нашей программы вы- полняется 5465 раз, и это занимает почти 5 секунд. На один вызов подпрограммы затрачивается приблизительно 1 милисекунда, следова- тельно частое обращение к этой подпрограмме является расточитель- ным.(в PRIME2PA соответствующая строка имеет номер 9.) Если в окне Execution Profile (Профиль выполнения) временная и количественная статистика показываются одновременно, то некото- рые сочетания этих данных заслуживают внимания. Для неэффективных подпрограмм вторая строка гистограммы (временные данные) гораздо длиннее, чем первая (количественные данные), это означает, что отношение времени выполнения к количеству вызовов велико. Именно такая ситуация наблюдается в строке 27, оператор printf (в Паска- левской программе это строка 28). В том случае, если для какой-то подпрограммы отношение обще- го времени ее выполнения к количеству ее вызовов велико, то самое лучшее из того, что можно предпринять - это попытаться заменить ее на другую подпрограмму. Рассматривая оператор return в подпрограмме root (строка 7), мы попадаем в другую ситуацию. Этот оператор характеризуется са- мым большим числом обращений и самым большим общим временем вы- полнения. К двум другим строкам (строке 5 и строке 8) обращение происходит 5456 раз, но гистограммы для каждой из этих строк по- казывают маленькие затраты времени на их выполнение. Такое соче- тание нас вполне устраивает, оно означает, что данные операторы работают быстро. Итак, самой большой проблемой на настоящий мо- мент является количество вызовов подпрограммы root. Сокращение количества вызовов подпрограммы (PRIME3). Теперь наша основная задача- это сокращение количества вызо- вов подпрограммы root. Загрузите PRIME3 в окно Module (Модуль), затем распахните это окно и посмотрите на исходный текст нашего примера. Информация для пользователей Паскаля: Вам следует за- грузить в окно Module (Модуль) пример PRIME3PA. Единственная модификация, имеющаяся в PRIME3, содержится в подпрограмме prime. Мы добавили новую целочисленную переменную limit и, перед началом работы цикла for, присвоили ей значение, равное root(n). Переменная limit - это верхняя граница для пара- метра цикла for. Информация для пользователей Паскаля: В PRIME3PA мы добавили целочисленную переменную Limit и положили ее равной корню квад- ратному из n перед началом выполнения цикла for. Переменная Limit - это верхняя граница для параметра цикла for. При помощи локального меню окна Module (Модуль), пометьте "области" на каждой строке программы. Во время данного сеанса профилирования (для того, чтобы запустить программу выберите Run| Run (Выполнение| Выполнение) или нажмите клавишу F9), программа работает немного быстрее. Общее время выполнения программы PRIME3 сократилось почти на 50%. Теперь в качестве основного потребителя времени выполнения выступает функция printf. За счет сокращения числа обращений к подпрограмме вычисления квадратного корня (с 5456 до 999) мы зна- чительно уменьшили общее время выполнения программы. Добавим еще немного эффективности. У нас осталось еще несколько возможностей для увеличения эф- фективности подпрограммы prime. Загрузите PRIME4 в окно Module (Модуль), затем просмотрите строки исходного текста с 8 по 17. Информация для пользователей Паскаля: загрузите PRIME4PA и изучите строки с 11 по 32. /* Copyright (c) 1990, Borland International */ #include |