В области оптимизации производительности Linux важнейшим фактором является производительность дискового ввода-вывода (I/O), которая существенно влияет на общую эффективность системы. Одним из ключевых параметров, влияющих на производительность дискового ввода-вывода, является максимальный размер I/O-запроса, определяемый параметром max_sectors_kb. Понимание и настройка этого параметра могут привести к значительному улучшению производительности системы. В этой статье мы рассмотрим понятие максимального размера I/O, его важность в системах Linux, а также его влияние на производительность в целом.
Параметр max_sectors_kb определяет максимальный размер отдельного I/O-запроса в килобайтах. Он устанавливает объём данных, который может быть передан в рамках одного I/O-запроса. Значение параметра max_sectors_kb ограничено логическим размером блока файловой системы и аппаратными возможностями устройства хранения данных. Оно не может быть меньше логического размера блока, делённого на 1024, и не должно превышать значение параметра max_hw_sectors_kb, который является параметром только для чтения и показывает максимально поддерживаемый аппаратурой размер запроса.
Минимальное значение = max(1, logical_block_size/1024)
Максимальное значение = max_hw_sectors_kb
Примечание: Максимальный размер I/O в Linux преимущественно применим к ядрам версии 4.x и выше. Рекомендуется проверить это в конкретном ядре вашей системы. Хотя впрочем очевидно - если у вас не какой-нибудь embedded, то ядро скорее всего будет выше 5.x
Важность в системах Linux
В Linux параметр максимального размера I/O существенно влияет на эффективность чтения и записи данных с устройств хранения. Он оказывает влияние на следующие аспекты производительности:
1. Баланс между пропускной способностью и задержками:
Пропускная способность (Throughput): Крупные размеры I/O-запросов увеличивают общую пропускную способность ввода-вывода за счёт обработки больших блоков данных за одну операцию. Это снижает накладные расходы на обработку множества мелких запросов, особенно эффективно при работе с последовательными потоками данных (видеостриминг, резервные копии баз данных).
Задержки (Latency): В то время как большие размеры I/O-запросов могут повысить пропускную способность для больших наборов наборов, они также могут увеличить задержку отдельных операций. Это происходит потому, что более крупные запросы требуют больше времени для завершения. Поэтому необходим баланс между улучшением производительности и допустимым уровнем задержек, особенно в чувствительных к задержкам интерактивных или real-time приложениях. В таких случаях предпочтительнее меньшие размеры запросов.
Факторы, влияющие на максимальный размер I/O
Есть несколько факторов, которые влияют на максимальный размер запросов в Linux:
Аппаратные ограничения: Значение max_sectors_kb не должно превышать аппаратные возможности накопителя (значение параметра max_hw_sectors_kb). Превышение аппаратного лимита может привести к ошибкам или снижению производительности.
Драйверы устройств: Драйверы контроллеров хранения и накопителей могут задавать свои лимиты на размер запросов.
Ограничения файловых систем: У разных файловых систем разные лимиты на размер запроса ввода-вывода.
Параметры ядра Linux: Настройки блочных устройств ядра влияют на размер запроса.
Бенчмаркинг и мониторинг
Для определения оптимального размера I/O-запросов необходимо проводить тестирование (бенчмарки) и мониторить показатели производительности (например, с помощью утилиты iostat).
Red Hat советует, чтобы значение max_sectors_kb было кратно оптимальному размеру I/O и внутреннему размеру блока стирания устройства. Если таких данных нет, рекомендуется выставить значение, совпадающее с логическим размером блока устройства.
Характеристики рабочей нагрузки: разные приложения выигрывают от разных размеров I/O.
Особенности накопителя: HDD и SSD имеют разные оптимальные диапазоны размеров I/O.
Ресурсы системы: доступная память и мощность CPU влияют на выбор оптимального размера I/O.
Практические аспекты настройки
Для настройки max_sectors_kb используется команда:
/sys/block/{device}/queue/max_sectors_kb
echo 256 | sudo tee /sys/block/sda/queue/max_sectors_kb
Данная команда устанавливает максимальный размер запроса в 256 КБ для диска /dev/sda. Перед изменениями желательно протестировать настройки на тестовой системе во избежание негативного влияния на производительность или стабильность системы.
Изменения параметра действуют только до перезагрузки системы. Чтобы изменения сохранялись, добавьте команду в rc.local или настройте сервис для применения параметров при загрузке.
Практическое исследование
Рассмотрим практический сценарий. Создадим лабораторную среду на Linux-сервере и проверим производительность диска. Нагрузку (IOPS) будем генерировать с помощью инструмента fio, а мониторинг производительности проводить с помощью утилиты iostat. Наша задача — оценить влияние параметра max_sectors_kb на производительность системы.
Тип EC2-инстанса: c5.12xlarge
EBS-том:
тип: GP3
размер: 20 GiB
IOPS: 3000
пропускная способность: 750 MB/s
Операционная система: Amazon Linux 2
Проверка дисков и установка fio
Для начала проверим доступные диски:
Мы будем создавать нагрузку на диск nvme1n1 при помощи утилиты fio и параллельно мониторить производительность диска, в частности показатель IOPS. Если fio не установлен, используйте команды ниже:
sudo apt-get install -y fio
Откройте два терминала одновременно:
Терминал 1: Генерируем нагрузку:
sudo fio --filename=/dev/nvme1n1 --rw=read --bs=256K --ioengine=libaio --direct=1 --name=volume-initialize
Терминал 2: Мониторим диск:
Обратите внимание, что в команде fio мы задали размер запроса 256 KiB.
На первом скриншоте видно, что утилита fio генерирует 1082 IOPS, однако утилита iostat показывает примерно 2164 IOPS (то есть в два раза больше).
Чтобы выяснить причину этого несоответствия, проверим значение параметра max_sectors_kb:
cat /sys/block/nvme1n1/queue/max_sectors_kb
Инструмент fio создавал IOPS с размером 256 KiB, а max_sectors_kb был установлен на значение 128 KiB. В результате ядро Linux разбивало каждый запрос на два меньших запроса по 128 KiB каждый (256 KiB = 128 KiB × 2). Именно поэтому количество операций, регистрируемых iostat, было в два раза больше, чем указывал fio (1082 × 2 = 2164).
Важно: Увеличение числа запросов из-за неправильно настроенного max_sectors_kb может негативно повлиять на производительность сервера и привести к троттлингу производительности диска (например, EBS-тома), если число операций превышает базовый уровень IOPS.
Проверка максимального аппаратного лимита max_hw_sectors_kb
Проверим максимальное значение I/O, которое поддерживает наш сервер:
cat /sys/block/nvme1n1/queue/max_hw_sectors_kb
Результат: наш сервер поддерживает максимальный размер I/O-запроса в 256 KiB.
Попытка увеличения max_sectors_kb
Попробуем увеличить значение до 512 KiB:
echo 512 | sudo tee /sys/block/nvme1n1/queue/max_sectors_kb
Результат: Мы получили ошибку «Invalid argument» («Недопустимый аргумент»), так как указали значение, превышающее аппаратный лимит max_hw_sectors_kb.
Теперь установим допустимое значение 256 KiB:
echo 256 | sudo tee /sys/block/nvme1n1/queue/max_sectors_kb
Результат: Значение успешно изменено на 256 KiB.
Повторный запуск теста fio
sudo fio --filename=/dev/nvme1n1 --rw=read --bs=256K --ioengine=libaio --direct=1 --name=volume-initialize
Результат: После изменения параметра max_sectors_kb количество операций IOPS, отображаемое fio и iostat, совпало.
Заключение:
Максимальный размер I/O-запроса (max_sectors_kb) является мощным инструментом для тонкой настройки производительности дисковой подсистемы в Linux. Правильно подобранное значение позволяет оптимизировать производительность ввода-вывода и снизить нагрузку на CPU, однако следует учитывать возможное увеличение задержек и аппаратные ограничения. Любые изменения параметров производительности следует предварительно тестировать и внимательно анализировать перед внедрением в продуктивную среду. Это гарантирует стабильность работы системы и её оптимальную производительность в различных сценариях.