Обратная связь
|
Эффективность выполнения программ
Эффективность программы во время выполнения определяется использованием двух ресурсов. Первый из них - необходимое для работы время, а второй — память, которая требуется программе. Время — более важный фактор для программиста, так как в большинстве случаев программа оценивается количеством машинного времени, необходимого для ее выполнения. Обычно проблема памяти существенна только тогда, когда ее недостаточно.
Оптимизировать память труднее, чем время выполнения. Нет ничего удивительного в том, что после оптимизации программа будет выполняться на 25% быстрее, но было бы необычно получить уменьшение размера используемой ею памяти на 25%; при этом предполагается, что не было допущено серьезных ошибок в первоначальном варианте программы.
Однако, что если бы вы выбрали новый лучший алгоритм и перепрограммировали задачу, то могли бы существенно улучшить как время выполнения, так и объем потребляемой памяти. Очень трудно значительно сократить используемую программой память, потому что сэкономленные области памяти разбросаны в небольших количествах по всей программе. В отличие от этого скорость выполнения можно значительно увеличить, например, оптимизируя такую часть программы, как цикл, который многократно повторяется.
Но иногда даже небольшая экономия памяти бывает просто необходима (чтобы можно было использовать конкретную программу для данной машины), тогда как небольшая экономия времени не так уже важна.
Мы увеличиваем эффективность выполнения программы, улучшая ее, насколько возможно, на стадии компилирования. Компилирование включает такие действия, как инициирование массивов и переменных, вычисление констант и распределение памяти. Распределение памяти на стадии компилирования обычно увеличивает расход памяти за счет сэкономленного времени выполнения программы.
Хорошие приемы программирования приводят к уменьшению как времени выполнения, так и объема используемой памяти, однако зачастую улучшение одного из этих факторов происходит за счет ухудшения другого. Большинство из обсуждающихся здесь методов экономит как время, так и память. Если использование метода приводит к возникновению конфликта между временем и памятью, это будет оговорено.
В большинстве случаев небольшое увеличение эффективности не имеет смысла, если оно связано с тратой значительного количества времени на программирование и вызывает ухудшение удобочитаемости, надежности, универсальности или удобства. Однако иногда это стоит делать. Типичным примером является компилятор, при создании которого затрачиваются большие усилия для получения эффективной программы. Но, поскольку компилятор используется неоднократно, даже малое увеличение эффективности приносит большие дивиденды. Эффективность также очень важна в библиотеках программ. Поскольку эти программы используются часто, небольшое увеличение эффективности будет, как правило, сокращать время работы машины. В каждом конкретном случае повышение эффективности зависит от ряда факторов, таких, как
- стоимость улучшения программы,
- частота ее использования,
- относительная скорость выполнения различных операций в машине,
- способ компилирования различных операторов.
Хорошей считается программа, которая выполняется при минимальном расходе машинного времени. В этом случае за данный отрезок времени можно выполнить еще и другие задания. С появлением мультипроцессорной обработки (т. е. выполнением более одного задания за то же время) стало желательным также и минимальное использование памяти, так как при работе в указанном режиме каждая программа должна находиться в оперативной памяти. Чем меньший объем памяти требуется каждой программе, тем больше программ можно разместить в оперативной памяти и обработать за одно и то же время. В режиме мультипроцессорной ^обработки использование оперативной памяти так же важно, как и расход времени. Сокращение занимаемой памяти или расхода времени будет уменьшать стоимость выполнения программы. Так как ресурсы машины очень дороги, то экономия даже небольшого количества времени или памяти в многократно используемой программе может вполне стоить затраченных усилий.
Обычно любая попытка улучшить эффективность предназначается для часто используемых программ. Хотя это весьма результативный подход, однако есть другой путь сэкономить большое количество машинного времени. Вырабатывайте комплекс привычек, которые будут способствовать составлению более эффективной программы и соответственно экономии машинного времени.
Оптимизация использования памяти
Обычно программисты не заботятся о памяти до тех пор, пока не превысят ее размеры. Тогда становится очевидным, что память не бесконечна. Идеальной считается ситуация, когда мы располагаем машиной с высоким быстродействием и достаточным объемом памяти. Однако размер задач увеличивается по мере увеличения размера памяти. Экономное использование памяти почти всегда сопровождается увеличением времени работы программистов и времени выполнения программы. Поэтому, если память не используется полностью, вопрос о ее распределении не представляет интереса до тех пор, пока ее достаточно.
Оверлейность программы
Под оверлейностью программы понимают возможность перенесения подпрограмм во время работы программы в быстродействующую память из некоторого другого типа памяти таким образом, что несколько подпрограмм в различное время занимают одну и ту же область памяти. Оверлейность используют в том случае, когда общие требования к объему программы превышают размер имеющейся в нашем распоряжении оперативной памяти. Программу следует разделить на логические части таким образом, чтобы не перекрывающиеся по времени части можно было последовательно вызывать в память по мере необходимости. Обычно для оверлейности используются программные модули. Чтобы пересылать модули из периферийной памяти, необходимо дополнительное время. Оверлейность экономит память, однако приводит к дополнительному расходу времени программистов высокого класса и машинного времени.
Виртуальная память
Возможность оверлейности реализуется также при использовании виртуальной памяти. Программисты полагают, что они имеют в своем распоряжении оперативную память очень большого объема даже на машине со сравнительно небольшим размером памяти. Однако, если для работы нужна часть программы, которой нет в оперативной памяти, теряется время: недостающая часть считывается с диска. Чем реже возникает такая ситуация, тем быстрее будет выполняться программа.
Программист может принять некоторые меры для повышения эффективности выполнения программы при использовании виртуальной памяти. Программу следует писать с подпрограммами. Это улучшает свойство локализованности программы, т. е. степени, до которой во время выполнения удается выделить в программе некоторый ее фрагмент. Это легко выполняемый прием программирования. Локализованность улучшается при использовании методов структурного программирования. Избегайте использования глобальных переменных, так как они приводят к ухудшению локальности. Организация циклов и подпрограмм также способствует локализованности, так как приводит к многократному выполнению небольшой части всей программы. Чем выше степень локализованности в программе, использующей виртуальную память, тем более эффективно будет выполняться программа, так как ей не придется вызывать в память много страниц. Таким образом, при использовании виртуальной памяти храните части программ, связанные друг с другом, рядом.
Другой способ повышения эффективности выполнения программ при использовании виртуальной памяти состоит в расположении подпрограмм в том порядке, в каком они будут обращаться друг к другу. Это уменьшит количество страниц, которые нужно будет считать в оперативную память.
Советы:
- Структурированные программы и использование модулей увеличат локализованность.
- Удаляйте подпрограммы, обрабатывающие исключения, подпрограммы обработки ошибок и другие редко используемые разделы программы из ее основной части, чтобы увеличить интенсивность обращений к наиболее часто используемым страницам.
- Присваивайте начальные значения элементам каждого массива данных непосредственно перед первым его использованием, а не перед началом работы программы.
- Обращайтесь к данным для считывания (или для записи) в порядке их расположения в памяти. Например, если массивы расположены в памяти по столбцам, выполните вначале все обращения к одному столбцу, прежде чем перейти к следующему.
- Данные, не являющиеся массивом, можно разместить рядом, перегруппировав их описания. Лучше всего располагать рядом наиболее часто используемые массивы.
Эквивалентность
В большинстве машинных языков предусмотрены операторы, позволяющие двум переменным занимать одну и ту же ячейку памяти. Если одна переменная используется только в начале программы, а вторая переменная нужна в другой части программы, обе переменные могут занимать одну и ту же ячейку памяти, так как они используются в программе в разное время.
Этот тип операторов можно применять для экономии памяти, потому что, как правило, в программе имеются переменные, которые используются только в отдельных сегментах программы. Установив эквивалентность массивов, можно сэкономить память, поэтому в программах, требующих большого объема памяти, этому вопросу следует уделить особое внимание. Традиционным способом сокращения объема памяти является уменьшение размера массивов. Это следует делать до установления эквивалентности двух массивов в памяти. А так как эквивалентность несвязанных переменных может быть неявно выраженной, ее следует соответствующим образом прокомментировать.
Использование циклов
Использование циклов для повторения последовательности операторов является обычным способом экономии памяти. Разные части программ нередко содержат одинаковые последовательности операторов. Если программист стремится к экономному расходованию памяти, он должен найти одинаковые части программы, которые могут быть преобразованы в циклы. Циклы требуют некоторого дополнительного количества памяти на инициирование, проверку, изменение индекса и установку всех констант. Однако уменьшение общего объема памяти за счет удаления повторяющихся команд весьма значительно. Не многократно повторяющиеся последовательности операторов, требующие сложной организации циклов, часто можно писать последовательно, а не итеративно.
|
|