Я попытался немного разобраться с этой темой и сделал ряд тестов в виртуальных машинах. Основные сложности тут следующие:
1️⃣ Если просто писать данные на диск с уровня операционной системы Linux, то она будет их кэшировать, пока у неё достаточно оперативной памяти для этого. Если не учитывать этот момент, то результаты будут разными в зависимости от объёма оперативной памяти и размера записываемых данных.
2️⃣ Если речь идёт о виртуальных машинах, то там есть слой кэширования гипервизора.
3️⃣ Если используется аппаратный рейд контроллер, то там есть свой слой кэширования, плюс запись в несколько потоков может идти быстрее, чем в один.
На практике это выглядит так. Берём виртуальную машину на Proxmox с 1G оперативной памяти и виртуальным диском без кэширования. Пробуем тесты на запись с помощью dd и разных флагов:
# dd if=/dev/zero of=/tempfile bs=1M count=512259 MB/s# dd if=/dev/zero of=/tempfile bs=1M count=2000247 MB/s# dd if=/dev/zero of=/tempfile bs=1M count=2000 oflag=direct240 MB/s# dd if=/dev/zero of=/tempfile bs=1M count=2000 oflag=dsync123 MB/s# dd if=/dev/zero of=/tempfile bs=1M count=2000 oflag=sync123 MB/sИспользуются флаги:
▪️direct - прямая запись в обход файлового кэша и синхронизации
▪️dsync - запись данных с синхронизацией каждого блока, то есть ждём подтверждение диска об успешной записи
▪️sync - запись данных и метаданных с синхронизацией
Результаты меня удивили. Я всегда был уверен, что запись dd по умолчанию будет вестись в кэш ОС, если хватает оперативной памяти. Я провёл много тестов на разных виртуалках, в разных гипервизорах, с разным количеством памяти в VM. И везде запись нулей из
/dev/zero на диск в кэш не попадала. Из-за большого количества тестов глаз замылился, и я не мог понять, в чём причина. Подумал уже, что по дефолту dd работает с флагом direct, но это не так.Причина вот в чём. Если файл
/tempfile уже существует, то запись ведётся напрямую, а если отсутствует и оперативы достаточно, то в кэш. Проверяем:# dd if=/dev/zero of=/tempfile bs=1M count=200231 MB/s# rm /tempfile# dd if=/dev/zero of=/tempfile bs=1M count=200635 MB/sЕсли взять ещё меньше файл, то скорость будет ещё больше:
# rm /tempfile# dd if=/dev/zero of=/tempfile bs=1M count=1001.6 GB/sЕсли вы будете писать с помощью dd обычный файл, который полностью помещается в оперативную память, то тоже при первичной записи файл попадёт в кэш:
# dd if=/tempfile of=/tempfile2 bs=1M count=128910 MB/sВсё было записано в кэш. Скорость диска мы вообще не увидели. Для тестирования линейной скорости записи на диск обязательно используйте флаг direct или sync. Значения вы получите разные в зависимости от флага, но они точно будут без использования кэша ОС.
А теперь я включу кэширование диска (Write back) на уровне гипервизора и выполню тесты с direct:
# dd if=/dev/zero of=/tempfile bs=1M count=2000 oflag=direct1.0 GB/sСкорость нереальная, так как файл не влезает в оперативку. Работает кэширование с уровня гипервизора, так что из VM измерить реальную скорость невозможно. Как зачастую невозможно и на арендованных VDS.
Интересная тема. Пару часов проковырялся с тестами, документацией, статьями. Забыл упомянуть, что погонял тесты с помощью sysbench, используя те же размеры блока и их количества. Результаты полностью совпадают с dd.
❗️Если при тестах диска вы видите очень большой разброс в значениях, у вас 100% где-то что-то залетает в кэш. Я не раз слышал от знакомых и читателей замечания по этому поводу. Люди получают сильно разные результаты тестов и не понимают, как их интерпретировать. Могут из-за этого ошибочно посчитать одно хранилище или формат диска быстрее другого.
#linux #disk