Как измеряется загрузка диска и почему 100% не означает, что он на пределе
Вы открываете iostat -x 1 на сервере, видите в столбце %util ровную сотню и делаете логичный вывод: диск захлебнулся, дальше только апгрейд или снижение нагрузки. На вращающемся HDD это чтение почти наверняка было бы верным. На современном NVMe — не факт, и даже часто не так: эта метрика измеряет не то, что кажется на первый взгляд, и для накопителей с глубокой очередью команд она регулярно вводит в заблуждение. Разберёмся, что именно считает iostat, почему сотня процентов перестала значить «предел», и на что смотреть вместо неё, чтобы понять реальную загрузку диска.
Содержание
Что показывает %util в iostat на самом деле
Формально %util — это доля времени интервала измерения, в течение которого у блочного устройства была хотя бы одна необработанная (outstanding) операция ввода-вывода. Источник данных — счётчик «время, потраченное на I/O» в /proc/diskstats (миллисекунды, накопительно с момента загрузки ядра). Утилита iostat берёт разницу этого счётчика между двумя снятиями, делит на длину интервала и умножает на 100 — получается процент.
Важный нюанс формулировки: устройство считается «занятым» в конкретный момент времени, если очередь не пуста — неважно, лежит там одна команда или тысяча. Метрика бинарна по своей природе: либо есть хоть что-то в работе, либо нет. Она не суммирует, сколько операций обрабатывается параллельно, и не измеряет, насколько близко устройство подошло к своему реальному потолку пропускной способности.
Хорошая аналогия — кассир в супермаркете, которого менеджер считает «занятым», пока у кассы стоит хотя бы один человек. Кассир одинаково «занят», если в очереди один покупатель или пятьдесят. Для оценки того, справляется ли касса с потоком, эта метрика бесполезна — нужно смотреть на длину очереди и на то, сколько времени люди реально стоят.
Почему эта метрика была честной для дисков с очередью глубиной 1
Классические жёсткие диски физически обрабатывают операции последовательно: одна головка, один актуатор, одна операция чтения или записи выполняется за раз, следующая ждёт своей очереди. Ранние интерфейсы (IDE, затем SATA без NCQ) не давали накопителю выбора — команды выполнялись строго по одной. Даже с появлением NCQ (Native Command Queuing) на SATA глубина очереди ограничена 32 командами, и на вращающемся диске это не сильно меняет картину: механика всё равно узкое место.
В таких условиях «очередь не пуста» и «диск физически занят обработкой» — практически синонимы. Если %util держится на 100%, значит, накопитель почти постоянно что-то делает и свободного времени на новые запросы у него не остаётся. Отсюда родилась многолетняя практика: %util — сигнал насыщения, увидел сотню — диск исчерпал резерв. Для HDD и для SATA SSD с низкой параллельностью это правило работает достаточно хорошо и по сей день.
Если хотите разобраться, откуда вообще берётся понятие глубины очереди и почему для разных типов накопителей она такая разная, у нас есть отдельный разбор: очередь команд NVMe и откуда берётся глубина очереди.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверNVMe меняет масштаб очереди на порядки
NVMe проектировался не поверх наследия жёстких дисков, а специально под флеш-память с её массовым параллелизмом. Спецификация допускает до 65535 очередей ввода-вывода, и каждая может содержать до 65536 команд. Это не значит, что реальный контроллер использует такие цифры целиком — конкретная реализация зависит от прошивки и драйвера, — но порядок величины принципиально другой: SATA с его 32 командами против NVMe с тысячами возможных одновременных операций.
За этими очередями стоит физика накопителя: современный SSD или NVMe-диск — это не одна «головка», а массив флеш-чипов, объединённых в несколько независимых каналов. Контроллер может параллельно читать и писать сразу на нескольких чипах, поэтому смысла обрабатывать команды строго по одной у него просто нет — архитектура специально построена так, чтобы держать в работе много запросов одновременно и тем самым скрывать задержку каждого отдельного чипа за счёт параллелизма.
Отсюда прямое следствие для %util: «очередь не пуста» на NVMe больше не означает «устройство работает на пределе своих возможностей». Она может быть не пуста практически постоянно просто потому, что приложение непрерывно подаёт новые запросы, а диск при этом обрабатывает их параллельно, с большим запасом по факту. Подробнее о том, почему один поток операций вообще не может выжать из NVMe его паспортную производительность и при чём тут параллелизм, — в статье NVMe и очереди: почему один поток не выжимает из диска максимум.
Как выглядит вводящая в заблуждение сотня процентов
Представим типичный сценарий на сервере с NVMe: база данных под нагрузкой, несколько воркеров бэкапа, логирование — в сумме десятки параллельных мелких операций чтения-записи почти без пауз. Каждая отдельная операция завершается быстро, но следующая уже стоит в очереди, пока предыдущая ещё не подтверждена. В результате очередь устройства почти никогда не бывает по-настоящему пустой между двумя соседними замерами iostat, и %util упирается в 100%, хотя реальная загрузка контроллера может быть далека от предела.
Отличить настоящее насыщение от ложного помогает связка из трёх показателей одновременно, а не один %util:
%util= 100%, задержка (r_await/w_await) низкая и стабильная, пропускная способность далека от паспортной — диск не перегружен, очередь просто редко пустеет из-за постоянного потока мелких запросов. Это нормальное рабочее состояние высоконагруженного, но здорового накопителя.%util= 100%, задержка растёт, пропускная способность приближается к паспортному потолку — вот это уже настоящее насыщение: диск действительно не успевает, и дальнейший рост нагрузки будет упираться в него.%utilзаметно ниже 100%, но задержка всё равно высокая — тоже возможный сценарий, обычно указывает не на сам диск, а на что-то выше по стеку: троттлинг на уровне гипервизора или cgroup, лимиты провайдера, проблемы в файловой системе.
Ключевая ошибка — судить о состоянии диска по одной цифре в отрыве от остальных. %util отвечает на вопрос «был ли диск хоть чем-то занят», а не «насколько сильно он занят» и не «успевает ли он».
Какие метрики реальнее отражают предел диска
Если %util больше не годится как единственный индикатор, вот что действительно стоит смотреть в выводе iostat -x:
r_awaitиw_await— среднее время отклика на операцию чтения и записи в миллисекундах, с учётом времени ожидания в очереди и самой обработки. Это то, что реально чувствует приложение. Ориентируйтесь не на абстрактное «хорошее» число (у разных накопителей и профилей нагрузки оно своё), а на тренд относительно вашей же базовой линии при низкой нагрузке: если задержка стабильно растёт по сравнению с типичной для этого диска и этого профиля запросов — это тревожный сигнал вне зависимости от того, что показывает%util.aqu-sz(в старых версиях —avgqu-sz) — средний размер очереди запросов к устройству. Показывает, сколько операций реально ожидает обработки одновременно, а не просто факт «очередь не пуста».- Пропускная способность (
rkB/s,wkB/s) и IOPS в сравнении с паспортными характеристиками накопителя. Реальный потолок — это данные производителя для последовательного и случайного доступа при разных размерах блока, а не наблюдение за одним процентом в мониторинге. Если фактическая нагрузка идёт с большим запасом до этих цифр, диск явно не на пределе, каким бы ни был%util. svctmв современных версияхiostatне выводится и считается ненадёжным полем ещё с эпохи однопоточных очередей — не стоит на него ориентироваться, если он вообще появляется в вашей версии утилиты.
Таблица ниже — не измеренные цифры, а ориентир по логике интерпретации, который стоит держать в голове при чтении вывода iostat -x:
| Сочетание показателей | Что это значит |
|---|---|
%util высокий, r_await/w_await низкие и стабильные, throughput далёк от паспортного | Диск здоров, очередь просто редко пустует |
%util высокий, задержка растёт, throughput близок к паспортному | Диск действительно насыщен |
%util низкий, задержка высокая | Проблема не в самом диске, ищите выше по стеку (гипервизор, cgroup, ФС) |
%util низкий, задержка низкая | Резерв есть, всё в порядке |
Как проверить диск честно, не полагаясь на один процент
Разовый снимок iostat мало что говорит — важна динамика. Практический подход:
- Снимайте метрики с интервалом и смотрите тренд, а не единичное значение:
iostat -x 1
Обращайте внимание на то, как r_await, w_await и aqu-sz ведут себя во времени относительно нагрузки, а не на то, что происходит в один конкретный момент.
- Постройте собственную базовую линию для этого конкретного диска в этой конкретной системе — в окне низкой нагрузки зафиксируйте, какая задержка и пропускная способность для него типичны. Без этой базы любое «высокое» или «низкое» число — просто ощущение, а не факт.
- Проверьте паспортный потолок отдельно, вне продакшен-нагрузки, синтетическим тестом — например, утилитой
fioс разными профилями (последовательный/случайный доступ, разная глубина очередиiodepth, разный размер блока). Так вы увидите, на каком реальном уровне задержка и throughput начинают деградировать нелинейно — это и есть настоящий предел устройства, а не догадка по проценту в мониторинге. Как честно и без искажений собрать такой тест, разобрано в статье fio для честного замера диска.
- Учитывайте, что вы на VPS или выделенном сервере видите не всегда «сырой» диск. Виртуализация, лимиты провайдера или троттлинг на уровне гипервизора могут искажать картину ещё до того, как данные попадут в
iostatгостевой системы. Если подозреваете именно это — общий чек-лист диагностики медленного диска на виртуальной машине есть в статье медленный диск на VPS: как проверить.
Практическое правило, которое стоит держать в голове вместо механического чтения одной цифры: сотня процентов %util сама по себе — не инцидент. Инцидент — это сотня процентов вместе с растущей задержкой и пропускной способностью, упирающейся в паспортный потолок диска.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Если %util показывает 100%, а сайт или приложение не тормозят — это нормально?
Да, вполне может быть нормой, особенно на NVMe с большим количеством параллельных мелких запросов. Проверьте r_await/w_await — если задержка низкая и стабильная, а throughput далёк от паспортного, повода для беспокойства нет.
На HDD и на SSD/NVMe эта метрика значит одно и то же?
Формула расчёта одна и та же, но интерпретация разная. На HDD с очередью глубиной 1 «очередь не пуста» почти равно «диск физически занят обработкой», поэтому 100% там действительно чаще указывает на насыщение. На NVMe с глубокой параллельной очередью это соответствие ломается.
%util низкий, но приложение всё равно тормозит на дисковых операциях — в чём дело?
Скорее всего, узкое место не в самом накопителе. Стоит проверить троттлинг на уровне гипервизора или cgroup, лимиты провайдера по IOPS/throughput, состояние файловой системы и наличие большого числа синхронных fsync-вызовов, которые создают задержку не из-за занятости диска, а из-за политики записи.
Как понять паспортный предел диска, если это виртуальный том на VPS, а не физический накопитель?
У провайдера обычно указаны лимиты по IOPS и пропускной способности для конкретного тарифа или типа диска — их и стоит считать «паспортом» вместо характеристик физического накопителя под капотом. Синтетический тест fio в окне низкой нагрузки покажет, на каком уровне эти лимиты реально начинают ощущаться.
Стоит ли вообще смотреть на %util, если он такой неоднозначный?
Смотреть стоит — как на индикатор «диск вообще что-то делает» и часть общей картины, но не как на единственный критерий насыщения. В связке с задержкой и пропускной способностью он остаётся полезным, сам по себе — вводит в заблуждение на современных накопителях.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →