Перейти на главную   
  helloworld.ru - документация и книги по программированию  
helloworld.ru - документация и книги по программированию
    главная     хостинг    
Поиск по сайту:  
Смотрите также
Языки программирования
C#
MS Visual C++
Borland C++
C++ Builder
Visual Basic
Quick Basic
Turbo Pascal
Delphi
JavaScript
Java
PHP
Perl
Assembler
AutoLisp
Fortran
Python
1C

Интернет-технологии
HTML
VRML
HTTP
CGI
FTP
Proxy
DNS
протоколы TCP/IP
Apache

Web-дизайн
HTML
Дизайн
VRML
PhotoShop
Cookie
CGI
SSI
CSS
ASP
PHP
Perl

Программирование игр
DirectDraw
DirectSound
Direct3D
OpenGL
3D-графика
Графика под DOS

Алгоритмы
Численные методы
Обработка данных

Сис. программирование
Драйверы

Базы данных
MySQL
SQL

Другое

Хостинг


Друзья
demaker.ru
Реклама

Лучший хостинг. Аренда серверов




helloworld.ru

Глава 23. Автоматическая оптимизация

             В Borland Pascal выполняется несколько различных типов опти-
        мизации  кода,  начиная  от свертывания констант и вычисления бу-
        левских выражений по короткой схеме и кончая  эффективной  компо-
        новкой. Рассмотрим некоторые виды оптимизации.


Свертывание констант

Если участвующие в операции операнды представляют собой константы перечислимого типа, то в Borland такое выражение вычис- ляется во время компиляции. Например, выражение: Х := 3 + 4 * 2 приведет к генерации такого же кода, как выражение Х := 11, а вы- ражение: S := 'In' + 'Out' генерирует тот же код, что S := 'InOut'. Аналогично, если операнды функций Abs, Sqr, Succ, Pred, Odd, Lo, Hi и Swap представляют собой константы перечислимого типа, то функция вычисляется во время компиляции. Если индексом массива является константа или выражение, сос- тоящее из констант, то адрес элемента вычисляется во время компи- ляции. Например, доступ к элементу Dаtа[5,5] так же эффективен, как доступ к простой переменной.

Слияние констант

Использование одной и той же строковой константы два или бо- лее раз приводит к генерации только одной копии константы. Напри- мер, два или более оператора Write('Dоnе') в одной и той же части программы приведет к ссылке на одну и ту же копию строковой конс- танты 'Donе'.

Вычисление по короткой схеме

В Borland Pascal реализуется вычисление булевского выражения по короткой схеме. Это означает, что вычисление булевского выра- жения прекращается, как только результат всего булевского выраже- ния становится очевидным. При этом обеспечивается минимальное время выполнения и, обычно, минимальный размер объектного кода. Вычисление по короткой схеме делает также возможным вычисление конструкций, которые иначе были бы недопустимыми. Например: while (I<=Length(S)) and (S[I]<>' ') do Inc(I); while (P<>nil) and (P^.Value<>5) do P:=P^.Next; В обоих случаях, если первая проверка имеет значение Falsе, вторая проверка не вычисляется. Противоположным вычислению по короткой схеме является полное вычисление, которое можно выбрать с помощью директивы компилятора {$В+}. В этом случае обеспечивается вычисление каждого операнда булевского выражения.

Параметры-константы

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

Устранение избыточной загрузки указателей

В определенных ситуациях генератор кода Borland Pascal может устранить избыточные инструкции загрузки указателей, уменьшая тем самым размер кода и обеспечивая более быстрое его выполнение. Когда генератор кода может обеспечить, что указатель остается постоянным на участке линейного кода (кода, не содержащего пере- ходов на него), и когда указатель уже загружен в пару регистров (например, ES:DI), генератор кода устраняет ненужные загрузки указателей в блоке кода. Указатель считается константой, если он получается из пара- метра-переменной (параметры-переменные всегда передаются как ука- затели) или из ссылки на переменную оператор with. Поэтому опера- тор with часто является более эффективным (но никогда не будет менее эффективным), чем запись для каждой ссылки на элемент пол- ностью уточненной переменной.

Подстановка констант множественного типа

Когда правая часть оператор in является константой множест- венного типа, компилятор генерирует включение проверки с помощью команд CMP. Такие поставляемые проверки более эффективны чем код, генерируемый в противном случае соответствующими булевскими выра- жениями с использованием операций отношения. Например, оператор: if ((Ch >= 'A') and (Ch <: 'Z')) or ((Ch >= 'a') and (Ch <= 'z')) then ...; менее читаем и менее эффективен чем if Ch in ['A'..'Z', 'a'..'z'] then ...; Поскольку свертывание констант применяется к константам мно- жественного типа также как к константам других типов, можно ис- пользовать описания const без потери эффективности. const Upper = ['A'..'Z']; Lower = ['a'..'z']; Alpha = Upper + Lower; С учетом данных описаний оператор if генерирует тот же код, что и в случае предыдущего оператор if: if Ch in Alpha then ... ;

Малые множества

Для операций с малыми множествами компилятор генерирует очень эффективный код. Малое множество - это множество с нижним порядковым значением в диапазоне 0..7 и верхним порядковым значе- нием в диапазоне 0..15. Например, следующие множества TByteSet и TWordSet являются малыми множествами: type TByteSet = set of 0..7; TWordSet = set of 0..15; Операции с малыми множествами, такие как объединение (+), разность (-), пересечение (*) и проверка на включение in генери- руют с помощью операций AND, OR, NOT и TEST вместо вызова библио- тек исполняющей системы инструкции машинного кода. Аналогично, стандартные процедуры Include и Exclude генерируют при применении к малым множествам поставляемый код.

Порядок вычисления

Стандартами Паскаля допускается, что операнды в выражении часто вычисляются в порядке, отличном от того, в котором они за- писаны (слева направо). Например, оператор: I := F(J) div G(J) где F и G - функции целого типа, приводит к тому, что G вычисля- ется перед вычислением F, так как это позволяет компилятору полу- чить более оптимальный объектный код. Важно, поэтому, чтобы выра- жение никогда не зависело от какого-то конкретного порядка вычисления встроенных функций. Если вернуться к предыдущему при- меру, то для того, чтобы вызвать функцию F перед функцией G, мож- но использовать временную переменную: T := F(J); I := T div G(J); Исключением из этого правила является вычисление по короткой схеме (разрешенное директивой компилятора {$B-}, при котором опе- ранды булевского типа, связанные операциями and или оr, всегда вычисляются слева направо.

Проверка на допустимость границ

Присваивание константы переменной и использование константы в качестве значения параметра проверяется во время компиляции на допустимость нахождения в заданных границах. При этом генерирует- ся такой код, что во время выполнения таких проверок не делается. Например, Х := 999, где Х - переменная байтового типа (Bytе), приводит к ошибке компиляции.

Использование сдвига вместо умножения

Операция X*C, где C - константа, являющаяся степенью числа 2, приводит к генерации объектного кода, в котором используется инструкция Shl (сдвиг влево). Аналогично, когда размерность массива представляет собой степень числа 2, то для вычисления индексных выражений использу- ется инструкция Shl (а не инструкция Мul).

Автоматическое выравнивание на границу слова

По умолчанию Borland Pascal выравнивает все переменные и ти- пизованные константы, превышающие по размеру 1 байт, на границу машинного слова. На всех 16-разрядных процессорах семейства 80х86 выравнивание на границу слова означает более быстрое выполнение, поскольку доступ к элементам размером в слово или четным адресам осуществляется быстрее, чем к словам по нечетному адресу. Выравнивание данных управляется директивой компилятора $A. По умолчанию в состоянии {$A+} переменные и типизованные констан- ты выравниваются указанным выше образом. В состоянии {$A-} ника- ких действий по выравниванию не производится. Примечание: Дальнейшие подробности приведены в Главе 2 ("Директивы компилятора") "Справочного руководства програм- миста".

Удаление неиспользуемого кода

Операторы, о которых известно, что они никогда не будут вы- полняться, не включаются в объектный код. Данные выражения, нап- ример, не приведут к генерации объектного кода: if false then statement { оператор } while false do statement

Эффективная компоновка

Компоновщик Borland Pascal автоматически удаляет неиспользу- емый код (по процедурам), то есть процедуры и функции, являющиеся частью скомпилированной программы, но к которым нет обращений, не включаются в файл типа .EXE. Процедуры, функции, переменные и ти- пизованные константы, участвующие в процессе компиляции, но ссыл- ки на которые отсутствуют, удаляются из файлa .EXE. Удаление не- используемого кода выполняется по процедурам, а удаление неис- пользуемых данных - по секциям, где эти данные описываются. Рассмотрим следующую программу: program SmartLink; const H: array[0..15] of char = '0123456789ABCDEF'; var I,J : integer; X,Y : real; var S: string[79]; var A: array[1..10000] of integer; procedure P1: begin A[1] = 1; end; procedure P2; begin I := 1; end; procedure P3; begin S := 'Borland Pascal'; P2; end; begin P3; end; Основная программа вызывает процедуру P3, которая вызывает процедуру P2, поэтому обе процедуры P2 и P3 включаются в файл .EXE. Поскольку P2 ссылается на первый раздел описания перемен- ных, а P3 ссылается на второй раздел описание переменных, пере- менные I, J, X, Y, S также включаются в выполняемый файл. Однако на процедуру P1 никаких ссылок нет, а включенные в выполняемый файл процедуры не ссылаются на переменные Н и A, поэтому эти объ- екты удаляются. Эффективная компоновка имеет особую ценность в связи с ис- пользованием модулей, которые реализуют библиотеки процедур и функций. Примером такого модуля является стандартный модуль Dos, который содержит ряд процедур и функций. При этом программа редко использует все эти процедуры. Если она использует только одну или две процедуры или функции, то только эти процедуры включаются в полученный в результате код.

[ Назад | Оглавление | Далее ]










helloworld.ru © 2001-2021
Все права защищены