Оптимизация Linux 1

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

Первое, что мы будем изменять, это файл /etc/profile. Файл /etc/profile содержит системное окружение всех исполняемых программ. Все настройки, добавленные в этот файл, отражаются на переменные окружения вашей системы. Так, поместив в этот файл флаги оптимизации, мы получим увеличение производительности компилируемых программ. Чтобы выжать максимальную эффективность из ваших программ, при компиляции вы можете использовать флаг -09, обозначающий полную оптимизацию по скорости. В Makefile многих программ, которые вы компилируете, содержится опция -02. Но, поставив вместо нее -09, мы получим высший уровень оптимизации, при которой размер файла увеличивается, но увеличивается и скорость выполнения.
Замечание. Использование опции -09 не всегда приводит к наилучшим результатам. Опцию следует использовать для процессоров x686 и выше, но не для более старых процессоров.
Также при компиляции можно использовать опцию -fomit-frame-pointer, которая говорит, что для доступа к переменным нужно использовать стек. К сожалению, с этой опцией практически невозможна отладка. Также можно использовать переключатели -mcpu=cpu_type и -march=cpu_type, при помощи которых создается код, оптимизированный под определенный CPU. Полученный код будет работать только на заданном процессоре или более новом.

Итак, приведенные ниже оптимизационные флаги запишем в файл /etc/profile (они влияют только на программы, которые вы будете компилировать в дальнейшем, и не оказывают никакого действия на существующие файлы):
— для CPU i686 или PentiumPro, Pentium II, Pentium III в файл "/etc/profile" добавьте следующую строку: CFLAGS='-O9 -funroll-loops -ffast-math -malign-double -mcpu=pentiumpro -march=pentiumpro -fomit-frame-pointer -fno-exceptions'
— для CPU i586 или Pentium в файл "/etc/profile" добавьте следующую строку: CFLAGS='-O3 -march=pentium -mcpu=pentium -ffast-math -funroll-loops -fomit-frame-pointer -fforce-mem -fforce-addr -malign-double -fno-exceptions'
— для CPU i486 в файл "/etc/profile" добавьте следующую строку: CFLAGS='-O3 -funroll-all-loops -malign-double -mcpu=i486 -march=i486 -fomit-frame-pointer -fno-exceptions'

Сразу же после выбора типа процессора добавим в строку export файла "/etc/profile" переменные "CFLAGS LANG LESSCHARSET":
export PATH PS1 HOSTNAME HISTSIZE HISTFILESIZE USER LOGNAME MAIL INPUTRC CFLAGS LANG LESSCHARSET
Теперь выйдите из системы и вновь в нее войдите, чтобы опции, определенные переменной CFLAGS, вступили в силу и все программы и другие configure-утилиты стали ее учитывать. Оптимизация под Pentium (Pro/II/III) будет работать только с компиляторами egcs и pgcc. Egcc уже входит в стандартную поставку Linux. Ниже приведено описание опций, которые мы использовали:
-funroll-loops — выполняется оптимизация развертыванием циклов. Осуществляется для циклов, число итераций которых может быть определено во время компиляции или во время выполнения.
-funroll-all-loops — выполняется оптимизация развертыванием циклов. Развертывает все циклы, и обычно программы, скомпилированные с этой опцией, медленнее запускаются.
-ffast-math — эта опция разрешает GCC нарушать некоторые ANSI или IEEE правила и/или спецификации в интересах оптимизации кода по скорости выполнения. Например, это позволяет компилятору предполагать, что параметры к функции sqrt — неотрицательные числа.
-malign-double — контролирует, выравнивает ли GCC double, long double и long long переменные на двусловной границе или однословной границе.

Выравнивание double переменных на двусловной границе создает код, который выполняется на Pentium-процессорах несколько быстрее, расходуя больше памяти.
-mcpu=cpu_type — определяет значение типа процессора при планировании используемых инструкций. При определении конкретного типа CPU, GCC будет использовать инструкции специфичные для него. Если эта опция не определена, то будут использоваться только команды, работающие на i386 процессоре. Тип процессора I586 эквивалентен Pentium, i686 эквивалентен Pentium Pro, K6 — AMD.
-march=cpu_type — использовать инструкции для процессора cpu_type. Выбор типа процессора производится так же, как и для опции mcpu. Кроме того, использование опции -march=cpu_type подразумевает и использование опции -mcpu=cpu_type.
-fforce-mem — принуждает копировать операнды, хранящиеся в памяти, в регистры перед выполнением арифметических операций над ними. В результате получается более лучший код, в котором все ссылки на ячейки памяти потенциально общие подвыражения. Когда они не являются общими подвыражениями, то комбинации команд должны устранить отдельную загрузку регистра.
-fforce-addr — вынуждает копировать постоянные адреса памяти в регистры перед выполнением арифметических операций над ними. В результате может создаваться более хороший код, так же как и при -fforce-mem.
-fomit-frame-pointer — не сохранять frame pointer в регистре для функций, которые не нуждаются в этом. Это позволяет избежать инструкций на сохранение, определение и восстановление frame pointer, в то же время освобождая регистры для других функций. Это также делает невозможным отладку программы.

Следующее, на что стоит обратить внимание, это файл bdflush. Он вплотную связан с операциями в подсистеме виртуальной памяти ядра Linux и имеет некоторое влияние на использование диска. Этот файл (/proc/sys/vm/bdflush) контролирует операции демона ядра bdflush. Мы используем этот файл для улучшения производительности файловой системы. Изменяя некоторые значения в файле, принятые по умолчанию, мы добьемся, чтобы система стала более "отзывчивой", например, она ждет чуть больше при осуществлении записи на диск, что позволяет таким образом избегать некоторых конфликтов доступа.
За основу возьмем Red Hat Linux. По умолчанию bdflush в Red Hat Linux использует следующие значения: "40 500 64 256 500 3000 500 1884 2".

Для изменения значений в bdflush введите следующие команды на вашем терминале:
echo "100 1200 128 512 15 5000 500 1884 2"> /proc/sys/vm/bdflush

Вы можете добавить эту команду в /etc/rc.d/rc.local, чтобы она выполнялась каждый раз при загрузке компьютера. Для более свежих дистрибутивов следует использовать другой способ: в файл /etc/sysctl.conf добавьте следующую строку:
vm.bdflush = 100 1200 128 512 15 5000 500 1884 2

Чтобы изменения вступили в силу, надо перезагрузить систему.
В вышеприведенном примере согласно файлу документации /usr/src/linux/Documentation/sysctl/vm.txt первый параметр в % определяет максимальное число "грязных" буферов в кэше буферов. "Грязные" означают то, что содержимое буфера должно быть записано на диск. Присвоение этому параметру высокого значения означает, что Linux в течение долгого времени может задерживать запись на диск, но в то же время это означает, что когда это все же потребуется, то сброс всех буферов будет осуществляться дольше, т.к. самих "грязных" буферов будет больше. Низкое значение будет распределять операции ввода-вывода более равномерно.

Второй параметр (ndirty), которому мы присвоили значение 1200, определяет максимальное число "грязных" буферов, которые могут быть одновременно записаны. Высокое значение означает как бы отложенные, пульсирующие операции ввода-вывода, в то время как маленькое значение может приводить к нехватке памяти.

Третье значение (nrefill=128) определяет число буферов, которые bdflush будет добавлять в список свободных при вызове функции refill_freelist(). Чем выше число, тем больше памяти будет потрачено впустую и тем реже будет необходимо вызывать refill_freelist().

Следующий параметр — nref_dirt=512. Когда refill_freelist() натолкнется на больше, чем nref_dirt "грязных" буферов, то просыпается демон bdflush.
Параметры age_buffer (50*m) и age_super parameters (5*m) обозначают максимальное время, которое Linux ждет перед записью грязных буферов на диск. Значение выражено в мигах (clockticks), число мигов в секунду m=100. Как описывается в английской литературе, "age_buffer это "возраст" блоков данных, а age_super — "возраст" метаданных файловой системы" (дословный перевод).

Пятый параметр (15) и последние два (1884 и 2) не используются системой, так что мы оставим их значения по умолчанию.
Замечание. Читайте /usr/src/linux/Documentation/sysctl/vm.txt о том, как улучшить параметры ядра, связанные с виртуальной памятью.

Продолжение следует

X-Stranger
xstranger@tut.by


(c) компьютерная газета


Компьютерная газета. Статья была опубликована в номере 32 за 2001 год в рубрике soft :: linux

©1997-2024 Компьютерная газета