Как проверить NVMe: файловые тесты fio и оценка задержек

Как проверить NVMe: файловые тесты fio и оценка задержек

Как проверить NVMe: файловые тесты fio и оценка задержек

Если новый сервер готовится к работе с базой данных или файловым сервисом, скорости копирования одного большого файла недостаточно для приёмки системы хранения. Данные могут попасть в кеш, запись — ещё не сохраниться на накопителе, а фоновые задачи — повлиять на результат. Надёжнее зафиксировать тестовый файл, размер блока и параметры параллелизма, отдельно оценить пропускную способность и задержки, а затем сохранить исходные результаты для повторной проверки.

Выделенные серверы CloudUDP стандартно оснащены двумя накопителями NVMe по 1TB, каждый подключён напрямую; аппаратного RAID нет. Ниже на примере Debian 13 показано, как с помощью fio — инструмента для тестирования с настраиваемой нагрузкой ввода-вывода — проверить выбранную файловую систему. Тесты не записывают данные напрямую на блочное устройство, а их результаты не являются обещанием производительности рабочих приложений.

1. Определите границы теста и фактическое расположение данных

Файловый тест охватывает весь путь от файловой системы до накопителя, а не измеряет предельную производительность самого диска. На результат могут влиять шифрование, управление томами, зеркалирование и параметры монтирования. Прямое подключение двух накопителей само по себе не означает, что конкретный каталог использует их оба.

Сначала установите инструмент и проверьте целевой каталог. В примере /srv используется как предполагаемое место для теста. Если он находится не на нужной файловой системе, укажите её фактический каталог монтирования.

sudo apt-get install fio
findmnt -T /srv -o TARGET,SOURCE,FSTYPE,OPTIONS
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
df -h /srv
df -i /srv
fio --version

Проверьте свободное место, состояние монтирования и права доступа к каталогу. Не ориентируйтесь только на заявленную ёмкость накопителя: часть пространства занимают служебные структуры файловой системы и существующие данные. После полного заполнения тестового файла должен оставаться запас для роста рабочих данных.

Не передавайте тесту записи пути устройств вроде /dev/nvme…. Отдельный файл снижает риск случайной перезаписи данных, но не устраняет конкуренцию за ресурсы. По возможности выполняйте тест до запуска рабочих сервисов. Немедленно остановите его, если задержки сервисов выходят за нормальные пределы, свободное место приближается к установленному резерву или возникают ошибки ввода-вывода.

2. Создайте отдельный каталог и полностью подготовьте тестовый файл

Выполняйте все команды в одном сеансе Bash. С помощью административных прав создайте временный каталог, доступный только текущей учётной записи. Разместите в нём тестовый файл и результаты, чтобы не затронуть существующие рабочие файлы.

TESTDIR=$(sudo mktemp -d /srv/fio-acceptance.XXXXXX)
sudo chown "$(id -u):$(id -g)" "$TESTDIR"
chmod 700 "$TESTDIR"
export TESTDIR
printf '%s\n' "$TESTDIR"
findmnt -T "$TESTDIR"

В примере используется файл размером 1GiB. Это отправная точка для проверки процедуры, а не тест всей ёмкости хранилища или его длительной работы в установившемся режиме. В fio значение size=1G интерпретируется в двоичных единицах; его нельзя напрямую сопоставлять с заявленной ёмкостью устройства без учёта единиц. Убедившись, что места достаточно, сначала полностью заполните файл последовательной записью:

fio --name=prepare \
  --filename="$TESTDIR/test.bin" \
  --size=1G --rw=write --bs=1M \
  --ioengine=libaio --direct=1 \
  --iodepth=1 --numjobs=1 --end_fsync=1 \
  --group_reporting --output-format=json \
  --output="$TESTDIR/prepare.json"

Обязательно проверьте код завершения и поля ошибок в JSON. Если прямой ввод-вывод не поддерживается, сначала проверьте файловую систему и способ монтирования. Не переключайтесь незаметно на кешируемый ввод-вывод, продолжая сравнивать результаты. При ошибках на этапе подготовки последующие тесты чтения не дают надёжной основы для оценки.

Параметр direct=1 обычно позволяет обойти страничный кеш файловых данных, но не все кеши устройства. Параметр end_fsync=1 запрашивает синхронизацию в конце задания; это не означает, что каждая запись имитирует фиксацию транзакции в базе данных.

3. Зафиксируйте параметры и отдельно проверьте случайное чтение и запись

Сначала выполните случайное чтение одним заданием, затем — случайную запись. Так смешанная нагрузка не будет скрывать возможные проблемы. Во время теста не копируйте данные и не запускайте другие проверки хранилища.

fio --name=randread \
  --filename="$TESTDIR/test.bin" \
  --size=1G --rw=randread --bs=4k \
  --ioengine=libaio --direct=1 \
  --iodepth=8 --numjobs=1 \
  --time_based --runtime=30 --ramp_time=5 \
  --group_reporting --output-format=json \
  --output="$TESTDIR/randread-q8.json"
fio --name=randwrite \
  --filename="$TESTDIR/test.bin" \
  --size=1G --rw=randwrite --bs=4k \
  --ioengine=libaio --direct=1 \
  --iodepth=8 --numjobs=1 \
  --time_based --runtime=30 --ramp_time=5 \
  --end_fsync=1 --group_reporting \
  --output-format=json \
  --output="$TESTDIR/randwrite-q8.json"

Указанные длительность и время прогрева — лишь параметры теста. На короткий тест могут влиять кеш устройства, температура и фоновые операции обслуживания. По нему нельзя судить о производительности длительной записи.

Добавьте контрольный тест с малой глубиной очереди

В тесте чтения измените iodepth на 1, а имя выходного файла — на randread-q1.json. Остальные параметры оставьте без изменений. Глубина очереди задаёт допустимое число одновременно незавершённых запросов ввода-вывода. Это не число ядер CPU и не количество одновременных подключений к сервису.

Если при увеличении глубины очереди пропускная способность растёт, а хвостовые задержки заметно ухудшаются, это говорит лишь о компромиссе между пропускной способностью и временем ожидания при данной нагрузке. Не переносите такое значение напрямую в настройки пула подключений базы данных.

4. Оценивайте пропускную способность, IOPS и хвостовые задержки вместе

IOPS — число завершённых операций ввода-вывода в секунду. При фиксированном размере блока этот показатель связан с пропускной способностью; результаты с разными размерами блоков нельзя ранжировать только по IOPS. В JSON fio поле bw обычно выражается в KiB/s. При чтении результатов проверяйте версию и единицы измерения полей.

В первую очередь смотрите iops, поля пропускной способности, а также среднее значение и процентили clat_ns внутри read или write. Задержка завершения операции не равна в точности времени отклика приложения: ожидание в очередях приложения и его собственная обработка остаются за пределами этого измерения.

P99 означает, что примерно 99% запросов имеют задержку не выше указанного значения. Это не максимальная задержка. Если средние значения близки, но P99 растёт, небольшая доля запросов может ждать существенно дольше. Оценивать это нужно с учётом фактической глубины очереди и повторных тестов.

В отчёт о приёмке включите как минимум:

Также проверьте распределение фактической глубины ввода-вывода в отчёте fio. Настройка 8 не означает, что такая глубина поддерживалась на протяжении всего теста. При различиях в поведении движка ввода-вывода или файловой системы даже одинаковые номинальные параметры не гарантируют сопоставимость результатов.

5. Завершите приёмку повторными тестами, архивированием и очисткой

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

Если два накопителя нужно принять отдельно, выберите каталог на файловой системе каждого из них и выполните тесты последовательно с одинаковыми параметрами. Если оба каталога фактически находятся на одном томе, смена каталога не считается независимой проверкой второго накопителя.

При ошибках чтения или записи сначала сохраните исходный вывод и относящиеся к нему записи ядра, затем проверяйте файловую систему и тракт подключения устройства. Если ошибок нет, но результаты сильно колеблются, сначала исключите влияние других задач на сервере и изменения условий тестирования. Не делайте сразу вывод о неисправности оборудования.

После завершения скопируйте JSON, сведения о монтировании и записи команд в контролируемое место хранения архива. Убедитесь, что архив читается, затем проверьте тестовый каталог и удалите только файл, созданный в рамках этой проверки:

printf '%s\n' "$TESTDIR"
ls -lh -- "$TESTDIR"
rm -- "$TESTDIR/test.bin"

Убедившись, что оставшиеся файлы результатов сохранены в архиве, удалите их по одному. Когда каталог станет пустым, удалите его командой rmdir; не применяйте рекурсивное удаление к точкам монтирования устройств. Итоговый вывод должен звучать как «при этих параметрах и условиях нагрузки получены такие результаты», а не «этот накопитель всегда обеспечивает определённую скорость». Файловые базовые тесты помогают выявить явные отклонения, но перед запуском приложения всё равно необходима проверка с его реальным характером чтения и записи.

Часто задаваемые вопросы

Безопасен ли файловый тест fio для работающих служб?

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

Отключает ли direct=1 все кэши и измеряет ли скорость фиксации транзакций?

Нет. Прямой ввод-вывод обычно обходит страничный кэш файловых данных, но не все кэши устройства. Он не воспроизводит долговечную фиксацию транзакций; для неё нужна отдельная проверка приложения и синхронной записи.

Выделенный сервер EPYC 7543P от $454 в месяц

Выделенные серверы с помесячной арендой

Перед оплатой проверьте конфигурацию и итоговую сумму. Все цены указаны в долларах США.