необходимости заталкивая в него новые элементы и в конце высвобождая их все
одной операцией. Некоторые библиотеки С содержат специальную функцию alloca
для такого способа выделения памяти, хотя она и не входит в стандарт. В качестве
источника памяти она использует локальный стек вызовов; высвобождаются
элементы в тот момент, когда заканчивает работу функция, вызвавшая
alloca.
Буферизуйте ввод и вывод. При буферизации трансакции объединяются в блоки с
тем, чтобы часто исполняемые операции выполнялись с минимально возможными
затратами, а очень дорогостоящие операции выполнялись только в случае крайней
необходимости. Стоимость операции, таким образом, распределяется между
несколькими значениями данных. Например, когда программа на С вызывае-Aprintf,
символы сохраняются в буфере,
но не передаются операционной системе до тех
пор, пока буфер не будет заполнен или не поступит явный запрос на его очистку. В
свою очередь, операционная система может задержать запись данных на диск.
Помеха в том, что данные становятся видимыми после очистки буферов вывода; и
в.худшем случае — информация, содержащаяся в буфере
, при аварийной остановке
программы пропадает.
Специальные случаи обрабатывайте отдельно. Обрабатывая объекты одинакового
размера в отдельном коде, специализированные аллокато-ры уменьшают затраты
места и времени и при этом уменьшают степень фрагментации памяти. В
графической библиотеке для системы Inferno основная функция d raw была
написана насколько возможно просто и непосредственно. После того как она
заработала
в таком виде, началась оптимизация различных частных случаев,
выбранных в результате профилирования (по одному изменению за раз). Большим
плюсом являлось то, что оптимизированную версию всегда можно было сравнить с
исходной (мы уже говорили о прототипах, — это тот самый случай). В конце концов
оптимизации подверглось лишь незначительное число случаев — из-за того
, что
динамическое распределение вызовов функции рисования очень сильно зависело
собственно от вывода символов на экран; для многих случаев просто не имело
смысла писать какой-то особо умный код.
Используйте предварительное вычисление результатов. Иногда ускорить работу
программы можно предварительно вычислив некоторые значения. Мы проделали
это в спам-фильтре, вычислив заранее strlen(pat[i]) и
сохранив его в массиве patlen[i
]. Если графической системе приходится постоянно вычислять математическую
функцию вроде синуса, но только Для какого-то дискретного набора значений,
например только для целых значений градусов, то быстрее заранее вычислить
таблицу из 360 элементов (или вообще включить ее в программу в виде данных) и
обращаться к этой таблице по
индексу. Это типичный пример экономии времени за
счет места. Существует множество способов замены кода данными или выполнения
вычислений при компиляции для сохранения времени, а иногда и места. Например,
функции из библиотеки ctype, вроде isdigit, почти всегда реализованы с помощью
индексации в таблице битовых флагов, а не посредством вычисления
последовательности тестов.
Используйте приближенные значения
. Если идеальная аккуратность; вычислений не
нужна, лучше использовать типы данных с низкой точностью. На старых или
маломощных машинах, а также на машинах, симулирующих плавающую точку
программно, вычисления с плавающей точкой, выполняемые с обычной точностью,
происходят быстрее, чем с двойной точностью, так что для экономии времени стоит
использовать float вместо double. Подобный прием
используется в некоторых
современных графических редакторах. Стандарт IEEE для плавающей точки требует
"чистого выхода за пределы точности" (graceful underflow) no мере приближения