Проблемы быстродействия
Быстродействие никогда не выйдет из моды. Чтобы обеспечить максимальное быстродействие
программы, ее необходимо оптимизировать. Об этом знают все программисты, занимающиеся
разработкой аркадных игр. Их игры должны работать быстро, иначе они будут плохо продаваться. С
каждым годом игроки желают иметь все более высокое быстродействие. Каждая новая игра-бестселлер
устанавливает новые стандарты и поднимает планку еще выше — несомненно, в будущем
эта тенденция только усилится.
Впрочем, на аркадных играх (и играх вообще) свет клином не сошелся. Скажем, разработчики САПР,
графических редакторов, имитаторов и образовательных программ в меньшей степени озабочены
вопросами оптимизации и быстродействия, чем игровые программисты. Но все эти приложения тоже
должны работать достаточно быстро. Никому не нравится работать с медленными программами.
Пользователи желают, чтобы события на компьютере происходили сразу же, а не через несколько
секунд. Вполне достойный, но плохо оптимизированный пакет может проиграть в конкурентной
борьбе.
Не стоит полагать, что каждый пользователь, знакомясь с новой программой, говорит себе: «Пусть
эта штука работает побыстрее, а не то…» Быстродействие программы чаще оценивается на
подсознательном уровне. Работа с быстрой программой, мгновенно реагирующей на все ваши
желания, доставляет радость. Хорошее быстродействие вселяет в пользователя уверенность и
желание работать дальше. Медленные программы лишь испытывают наше терпение. Каждый, кому
приходится работать с ними, мечтают поскорее закончить свои мучения. Пользователи
предпочитают, чтобы любая программа (текстовый или графический редактор, игра или любое
другое приложение) быстро и адекватно реагировала на их действия.
В этой главе речь пойдет о некоторых практических аспектах быстродействия, знакомство с
которыми позволит вам поднять свои программы на новый уровень.
Эксперты по оптимизации программ написали многие тома на эту тему. Из их исследований мы
узнали много полезного о том, как написать программу, выполняющую свои функции за минимальное
время. В этой главе такая оптимизация не рассматривается — эта тема слишком обширна.
Усилия, затраченные на оптимизацию, окупаются лишь в некоторых частях программы. Не
стоит напрасно тратить время на возню с однократно выполняемым кодом, однако оптимизация кода
в циклах и часто вызываемых функциях оказывается жизненно важной.
Аппаратная часть быстрее программной. Приложение, которое работает в режиме 1024x768x24 и
при этом обеспечивает вывод 60 кадров в секунду, было бы невозможно написать без аппаратного
ускорения. Так как большинство движков автоматически использует все возможности для
аппаратного ускорения, вам даже не придется беспокоиться на этот счет. Я упоминаю об этом лишь
по одной причине: если компьютер пользователя не обладает возможностями аппаратного
ускорения (или такие возможности слабы), вам не удастся почти ничего сделать. Не стоит
беспокоиться о подобной ситуации, потому что проблема заключается в аппаратной части, а не в
вашей программе. Если можно, постарайтесь добиться оптимального быстродействия за счет
поддержки видеорежимов с низким разрешением. После этого можете считать, что сделали все
возможное.
Нехватка видеопамяти. На большинстве новых видеокарт установлено свыше 128 Мб памяти, но
многие карты имеют лишь 64 Мб. Это не так уж много. С увеличением разрешения проблема
становится еще острее. В зависимости от объема установленной памяти, можно рекомендовать
использование различных видеорежимов, обеспечивающих хорошее быстродействие.
Когда свободная видеопамять кончается, текстуры создаются в системной памяти. Хотя системная
память и обладает некоторыми преимуществами по сравнению с видеопамятью, быстродействие не
относится к их числу.
FPS - еще не все. В наши дни часто приходится слышать о частоте вывода кадров, или FPS (Frames
Per Second, количество кадров в секунду). Этот показатель стал критерием для сравнения
графических приложений. Однако, все же не стоит переоценивать важность этой характеристики.
FPS показывает, с какой частотой приложение обновляет информацию, выводимую видеокартой на
экран. Тем не менее может возникнуть ситуация, при которой частота генерации содержимого для
новых кадров превышает частоту смены кадров, установленную для видеокарты и монитора. В этом
случае часть кадров пропадет, потому что видеокарта не будет успевать выводить (а монитор —
отображать) генерируемые данные.
В идеальном варианте приложение должно генерировать кадры со скоростью, соответствующей
кадровой частоте видеокарты и монитора, и для этого есть несколько причин. Во-первых, такая
синхронизация предотвращает эффект расхождения, потому что монитор всегда выводит
полностью сформированное изображение. Во-вторых, нет смысла генерировать кадры быстрее, чем
человеческий глаз может их воспринимать. Частота смены кадров на мониторе выбирается с учетом
человеческого восприятия; следовательно, если приложение генерирует кадры с частотой их смены
монитором, то оно выводит максимум визуальной информации, воспринимаемой человеческим
глазом. Сказанное оказывается особенно справедливым для видеорежимов с частотой смены
кадров в 60 Гц и выше.
Долой аппаратную зависимость! Если в приложении используются возможности,
поддерживаемые лишь некоторыми видеокартами, такое приложение называется аппаратно-
зависимым (device-dependent). Приложение не должно полагаться на присутствие конкретной
видеокарты или ее специфические возможности, если только вы не пишете демонстрационную
программу для производителя этих видеокарт. Подобная зависимость ограничивает рынок сбыта и
раздражает пользователей, чьи видеокарты не обладают необходимыми аппаратными
возможностями.
Другой способ избежать аппаратной зависимости — протестировать приложение на максимальном
количестве разных аппаратных конфигураций. При этом может выясниться, что вы пользуетесь
возможностями своей видеокарты, не поддерживаемыми большинством других видеокарт. Всегда
лучше узнать об этом самому, чем услышать от недовольных потребителей.
Перестановка кресел на «Титанике». Вспоминая времена своей учебы, я понимаю, что в те времена
мы слишком беспокоились о быстродействии. Например, один профессор подсчитывал, сколько
дополнительных инструкций уходит на вызов функции. Он любил рассуждать о разнице в
быстродействии при использовании вызовов функций в стиле C и Паскаля и о преимуществах
развертки циклов. Он вырос в эпоху перфокарт и ассемблера. Его учили тщательно строить
программу на ассемблерном уровне, где приходится учитывать каждый байт, поэтому вполне
естественно, что он не выносил напрасной траты байтов и команд процессора. Действительно,
вызов функции требует нескольких лишних тактов, а уменьшение количества аргументов экономит
память в стеке, но что из того? Преимущества, получаемые от вызова функций и от использования
аргументов, оправдывают затраты.
По сравнению с техникой, применявшейся в эпоху перфокарт, современный компьютер невероятно
быстр и мощен. Экономить каждый байт в современном программном пакете — то же самое, что
пытаться переставлять кресла на палубе «Титаника». Никакого толку от этого занятия не будет,
хуже того, оно отвлечет вас от решения настоящих проблем с быстродействием.
Джефф Дантеманн,
"Графика для Windows средствами DirectDraw".