Статьи

Страница 1 из 3.   [1] [2] [3]

88 советов по оптимизации программ на Visual Basic


В номере за декабрь 1997 Visual Basic Programmers Journal Франциско Балена делится с читателями советами по оптимизации (скоростной) кода программ. Всего подобрано 88 советов Благодаря Александру Лапшину вы можете прочитать полный перевод.


Этим простым советам далеко до искусства оптимизации. Но вы можете ускорить свои приложения, придерживаясь их.

Компилятор VB фирмы Microsoft был сделан для быстрого выполнения VB программ. Однако при эффективном компиляторе и мощной аппаратуре некоторые куски кода очень тормозят, как Вы сами можете в этом убедиться. Для ускорения кода, воспользуйтесь следующими советами, которые помогут Вам «смазать» его наиболее тормозные места. За исключением нескольких оговоренных случаев, нет разницы, компилируете ли Вы свои приложения в native-код, или в p-код.

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

Все эти советы применимы к VB3, VB4 16- и 32-битной версии, и VB5, без видимых различий. Программисты на VB3 могут не читать об объектах, OLE серверах и RDO. Также программисты на VB3 и VB4 могут пропустить VB5-специфичные советы, такие, как ODBCDirect и режимы компиляции native кода. Код тестировался только под VB5; Вы должны исправить вызовы API для VB3 и VB4/16.

Последнее замечание: Я не тестировал программу на конкретное время, и Вы не увидите многих абсолютных значений времени в моей статье. При обсуждении подходов оптимизации я не могу помочь в сравнении производительности на разных системах при одинаковых подходах. Я проводил тестирование native компилированного кода на Pentium-120Мгц, под Windows 95. Эти времена могут отличаться для старых версий VB или p-кода VB5, и естественно производительность на разных системах и разных версиях Windows будет разная.


ПЕРЕМЕННЫЕ: ВСЕГДА ПРИДЕРЖИВАЙТЕСЬ ЭТИХ ПРАВИЛ.

1. Всегда используйте Integer или Long тип переменных, вместо Single, Double, или Currency где это возможно. Математические операции с типами Integer и Long делаются за 1 такт процессора, и следовательно гораздо быстрее.

2. Используйте Single вместо Double, если Вам не нужна точность Double. Переменная типа Single требует меньше памяти и работает быстрее в математических выражениях.

3. Не пользуйтесь типом Variant, если не нуждаетесь в его особенных свойствах, таких, например, как хранение величин типа Empty и Null. Каждая переменная Variant занимает 16 байт (против 8, занимаемых Double или Currency) и в общем очень тормозная.

4. Обязательно добавьте в раздел General каждого модуля директиву Option Explicit. Это снизит риск неумышленного использования необъявленных Variant-переменных. Как альтернативу можно использовать директиву DefLng A-Z , которая подразумевает, что все необъявленные переменные имеют тип Long. Добавьте предупреждение в начало модуля - это гарантирует, что редакторы не пропустят эти директивы.

5. Локальные переменные типа Static в 2-3 раза медленнее, чем обычные локальные переменные. Если Вы хотите ускорить свою программу, преобразуйте все статические переменные в переменные уровня модуля. Единственный недостаток этого подхода, это то, что процедуры, модуля, использующие их, станут модулезависимыми. И если Вы захотите перенести эти процедуры в другой проект, не забудьте перенести вместе с ними и переменные уровня модуля.

6. Ссылки на переменные, объявленные на уровне модуля быстрее, чем глобальные переменные, объявленные в отдельном модуле. Если Вам не нужен общий доступ к переменным из всех программ и модулей, объявляйте их только в тех модулях или формах, которые их используют.


ЯВНЫЕ И НЕЯВНЫЕ ПРЕОБРАЗОВАНИЯ.

7. Остерегайтесь использовать функции Int и Val - они всегда возвращают вещественное значение с плавающей точкой. Если вы используете Long или Integer применяйте CInt or CLng. Вы можете использовать 4 способа преобразования text-box величины в значение типа Integer или Long:

result% = Val(Text1.Text)
result% = Int(Text1.Text)
result% = CInt(Text1.Text)
result% = Text1.Text

Каждое последующее утверждение в этом коде немного быстрее, чем предыдущее; последнее - приблизительно на 30 процентов быстрее, чем первое.

8. Используйте "\" вместо "/" при делении целых. Избегайте лишних неявных преобразований, так как оператор "/" возвращает значение Single. Имейте в виду, что оператор "/" возвращает значение Double если по крайней мере один из элементов имеет тип Double. С другой стороны, если Вы хотите повысить точность вычислений при делении Single или Integer, Вы можете вручную привести один из аргументов к типу Double:

' Это печатает 0.3333333
? 1 / 3
' А это печатает 0.333333333333333
? 1 / 3#

9. Бейсик хранит константы , в наиболее простой форме - скажем константа несущая единицу хранится как целое, если вы предполагаете использовать ее для действий с вещественными числами, объявите ее явно:

Value# = Value# + 1# 

Это предотвратит компилятор от хранения ее в формате Double, и сохранит от одного преобразования при каждом обращении. Вы также можете использовать именованные константы:

Const ONE As Double = 1

УРОКИ МАТЕМАТИКИ.

10. Самые быстрые функции - те, результаты, работы которых Вы можете оценивать заранее. Например, сохранение факториалов всех чисел в диапазоне от одного до 100 в массив один раз в начале программы - намного быстрее, чем предположительные тысячи вызовов функции в течение работы приложения. Вы можете увидеть проблему такого подхода в том, что вычисляются все значения, даже те, которые не требуются во время выполнения программы, и придется держать глобальный массив значений. Это делает неудобным повторное использование Вашей разработки. Вы можете обойти эти проблемы путем использования массива Static в своей программе.

11. Используйте оператор And вместо Mod, когда делитель - число в формате 2 ^ N. Например, Вы можете использовать два метода для извлечения самого младшего байта в Integer:

lowByte% = value% Mod 256
' А так немного быстрее …
lowByte% = value% And 255

12. Используйте Boolean в операторах сравнения. Например:

If x <> 0 Or y <> 0 Then ... 
' Работает также как это: 
If x Or y Then ... 
' А это:
If x = 0 And y = 0 Then ...
' Также как это : 
If (x Or y) = 0 Then ... 

Даже оператор XOR может сэкономить немного времени:

If (x = 0 And y = 0) Or (x <> 0 And y <> 0) Then ...
' А быстрее так:
If (x = 0) Xor (y <> 0) Then ...

13. Иногда Вы можете заменить весь If...Else блок более простой логической операцией. Например, Вы можете заменить этот код:

If x > 0 Then y = 1 Else y = 0 

На другой, хотя и весьма загадочный:

y = -(x > 0)

Однако, это тот случай, когда жертвуется понятый синтаксис в пользу повышения производительности. При этом Вы обязательно должны добавить замечание, которое ясно объясняет, что ваш код делает, во избежании проблем с сопровождением в дальнейшем.


ПУТИ УСКОРЕНИЯ МАССИВОВ.

14. Чтение и запись элемента массива всегда медленнее, чем доступ к простой переменной. Следовательно, если Вы хотите использовать один и тот же элемент массива в цикле неоднократно, назначьте временной переменной ссылку на этот элемент, и используйте именно ее. В циклах повышение производительности может достигать 80 процентов

15. По той же самой причине, обращение к элементам в матрице медленнее, чем доступ к элементам в одномерном массиве. Примите это во внимание при проектировании ваших алгоритмов. Например, при программировании игры в шашки, лучше предпочесть одномерный массив на 64 элемента матрице 8 на 8.

16. При частом поиске в массиве, элементы которого не меняются, имеет смысл отсортировать элементы массива и воспользоваться быстрым двоичным поиском (binary search). С другой стороны, сортировка - медленная операция, и один из продвинутых подходов заключается в применении Хэш-таблиц (Hash tables), если у Вас достаточно памяти. Я не буду описывать Hash tables в этой статье, но Вы можете использовать их для оптимизации программы AnyDuplicates, как показано в. Вас удивят результаты.

17. Если Ваш массив типа Integer содержит элементы значением от 0 до 255 , то имеет смысл преобразовать его в массив типа Byte. Это не ускорит код, но уменьшит ресурсоемкость, что актуально для старых машин.

18. Копируйте блоки данных между массивами одного типа, используя функцию API CopyMemory вместо цикла For...Next:

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
	(Dest As Any, As Any, ByVal Bytes As Long)
' Копируем a() в b() - b() того же типа что и а()
' Размерность N показывает число копируемых элементов
CopyMemory b(0), a(0), n * Len(a(0)) 

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

19. Вы можете использовать эту функцию для сдвига элементов массива без цикла с вставкой или удалением одиночного элемента. (Я описываю эту технику в своей статье "Выжмите всё из своих массивов." VBPJ Июль 1997).

20. При работе с матрицами используя вложенные циклы - внешний цикл должен выполнить итерации на столбцах, а внутренний - итерации на строках (VB, сохраняет матрицы как один столбец после другого). Программа вызывает меньшее количество "листания".

Когда Вам надо просканировать большую двухмерную матрицу, работайте с ней, ориентируясь на столбцы. Другими словами внешний цикл For ... Next должен быть по столбцам, а внутренний - по строкам. При этом Вы работаете с элементами массива так, как они размещаются в памяти (VB хранит массивы в памяти столбцами - один после другого) и таким образом уменьшается страничная активность. См. мою статью "Выжмите всё из своих массивов." [VBPJ Июль 1997], для примера программы, которая в 10 раз быстрее, чем программа с инвертированным доступом в двух вложенных циклах.

21. Никогда не используйте For Each на Variant массивах. Обычный For Loop с Integer или Long индексом как минимум вдвое быстрее.

22. Если вы абсолютно уверены, что ваша программа VB5 никогда не выдает "Subscript out of range" error, компилируйте native код с опцией "Remove Array Bounds Check". Это может ускорить программу, интенсивно работающую с массивами, на 50% или более.


Страница 1 из 3.   [1] [2] [3]

   
Hosted by uCoz