Настройка производительности системы
Увеличение производительности дисковой подсистемы
Кроме очевидных советов купить более производительный компьютер с более быстрыми дисками, мы можем рассмотреть и другие рекомендации и выяснить, какие могут быть пути ускорения работы дисковой подсистемы уже существующего компьютера. Для этого мы познакомимся со структурой дисковой активности в Solaris и узнаем, как можно ее оптимизировать.
Дисковая активность (т.е. обращения к дискам с целью чтения или записи данных) вызывается в Solaris двумя источниками: пользовательскими процессами, которые выполняют чтение и запись информации, и подсистемой виртуальной памяти, которая выполняет свопинг или пейджинг.
Запись данных на диск бывает синхронной и асинхронной. В большинстве случаев процессы осуществляют асинхронную запись на диск: при выполнении записи данных в файл данные фактически записываются в кэш в памяти, и процесс получает уведомление об успешно завершившейся записи. На самом деле фактическая запись данных в файл происходит позднее, когда демон отложенной записи fsflush запишет сразу большую порцию данных из кэша на диск.
Приложение может вызвать функцию fsync() для принудительного сбрасывания данных из файлового кэша на диск. Кроме этого, к такому же результату приводит закрытие файла, используемого процессом. При завершении процесса все связанные с ним файлы закрываются, что вызывает немедленную запись всех еще не записанных в эти файлы данных из кэша на диск. Поэтому при одновременном завершении большого количества процессов дисковая активность может резко возрасти. Такое явление наблюдается, например, при завершении работы демона squid, кэширующего http-запросы.
Вторая причина дисковой активности, свопинг или пейджинг, зависит от того, как объем памяти в системе соответствует реальным потребностям приложений. Настройку системы с целью оптимизации свопинга мы рассмотрим ниже в разделе "Эффективное использование памяти и свопинга ", а сейчас обратимся к оптимизации операций записи и чтения данных.
Снижение частоты синхронизации файлового кэша с диском
При частых и объемных операциях с файлами, файловый кэш быстро заполняет значительный объем памяти. В системах Solaris до версии 8 он даже конкурировал с процессами за оперативную память. Процесс fsflush регулярно (по умолчанию - раз в 30 секунд) "сбрасывает" на диск содержимое кэша, обеспечивая таким образом синхронизацию кэша и файловой системы. Если количество открытых файлов велико, эта синхронизация может приводить и к потерям времени и к чересчур высокой загрузке дисковой подсистемы.
Демон fsflush руководствуется значением двух переменных, squid и tune_t_fsflushr, - значение им можно присвоить в файле /etc/system. Для систем с большим объемом памяти установленное по умолчанию значение squid в 30 с делает процесс fsflush чересчур дорогостоящим.
Для того чтобы поубавить аппетит fsflush, время цикла синхронизации следует увеличить, изменив в большую сторону значение squid. Поскольку fsflush оказывает влияние на всю систему, лучше всего, чтобы он работал в течение более коротких промежутков времени. Для этого значение tune_t_fsflushr (время, отведенное fsflush на синхронизацию) должно быть меньше: выделив демону меньшее число секунд, вы заставите его выполнять меньшую по объему запись.
Приостановка записи (write throttle) в файловой системе UFS
Одной из проблем в системах, где происходит частая запись больших объемов данных в файлы на диске, является использование слишком больших объемов оперативной памяти для буферов файлов. Пока запись в файл не завершена, буфер занимает место в памяти, и это снижает общую производительность системы. В Solaris придуман механизм борьбы с этим явлением.
Переменная ядра ufs:ufs_WRITES отвечает за включение механизма write throttling (приостановки записи в файл). Если эта переменная равна 1, то приостановка записи разрешена. По умолчанию это именно так.
Приостановка означает, что когда объем данных, ожидающих записи в один файл, превышает верхний предел ufs:ufs_HW, запись в этот файл блокируется до момента, пока объем данных в буфере не снизится до ufs:ufs_LW. Соответственно, пока запись в файл блокирована, пополнение буфера не осуществляется, зато данные из буфера записываются на диск, за счет чего буфер освобождается.
Настройка этих параметров ядра может понадобиться, если количество приостановок постоянно растет. Это можно заметить, изучив с помощью отладчика счетчик ядра ufs_throttles. Его значение увеличивается на единицу при каждой приостановке записи, и постоянное увеличение этого значения говорит о том, что пределы ufs:ufs_LW и ufs:ufs_HW следует увеличить.
Такое увеличение вполне допустимо и даже полезно при использовании метаустройств с расщеплением (striping metadevices), когда данные одного файла поблочно пишутся на несколько устройств одновременно (первый блок - на первый диск, следующий - на второй и т.д.), так как совокупная пропускная способность метаустройства выше, чем у одного физического диска. То же относится и к массивам RAID. Значения ufs:ufs_LW и ufs:ufs_HW не должны быть слишком близкими, но и не должны очень сильно отличаться. Если они слишком близки, то приостановки записи будут случаться очень часто: как только объем буфера окажется у нижнего предела и запись будет разрешена, буфер сразу превысит верхний предел и запись приостановится. Большая разница между значениями приведет к тому, что запись в файл будет заблокирована при превышении верхнего предела, и после этого пройдет значительное время до разблокировки записи, так как буфер не может быть мгновенно "сброшен" на диск, и до достижения нижнего предела придется ждать относительно долго.
Рекомендуется нижний предел устанавливать равным 1/32 объема оперативной памяти, а верхний - 1/16 этого объема.
Приостановка записи производится на пофайловой основе, т.е. блокировка записи в один файл, буфер которого заполнен более чем ufs:ufs_HW байтами, не влияет на запись в другие файлы.