Пять российских VPS на Linux: fio, sysbench и грабли

от автора

Обзоров VPS на Хабре хватает, но почти все сделаны Windows-утилитами и сводятся к тому, какой диск показал «отличный результат». Мне же нужна была батарея, которую можно прогнать по SSH на любой машине, и понимание, что конкретно означает каждое число.

Второй пункт оказался неожиданно объёмным. Я трижды получал красивые результаты, которые не имели отношения к тому, что я думал измерить: скорость оперативки вместо диска, кэш гипервизора вместо носителя, конфиг лимитера вместо производительности. Каждый раз цифры выглядели совершенно правдоподобно, и я бы их спокойно опубликовал.

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

Подопытные

Все характеристики сняты с самих машин (lscpu, free, lsblk, systemd-detect-virt, /etc/os-release).

Провайдер

CPU

Гипервизор

Ядер

RAM, ГБ

Диск, ГБ

Тип диска¹

ОС

SmartApe

Intel Xeon Processor (Cascadelake)

kvm

4

1.9

40

NVMe

Ubuntu 26.04 LTS

IHC.host

Intel Xeon Processor (Cascadelake)

kvm

4

7.8

75

NVMe

Ubuntu 24.04.4 LTS

Cloud4U

Intel(R) Xeon(R) Gold 6248 CPU @ 2.50GHz

vmware

4

7.8

32

NVMe

Ubuntu 22.04.2 LTS

RUVDS

Intel(R) Xeon(R) Gold 6152 CPU @ 2.10GHz

hyperv

4

3.8

40

NVMe

Ubuntu 24.04 LTS

Reg.ru

Intel Xeon Processor (Icelake)

kvm

4

7.8

80

NVMe

Ubuntu 24.04.3 LTS

¹Тип диска – единственная строка, которая не измерена, а процитирована по заявлению провайдера. Вернусь к этому в разделе с оговорками, там же объясню, почему проверить это изнутри ВМ нельзя.

Методика

Три полных прохода батареи на каждый хост – не три повтора одного теста подряд, а три круга. Так повторы одной метрики разнесены во времени и меньше ловят локальный шум соседей по гипервизору. Пауза 20 с после каждого теста, итог по метрике – медиана трёх проходов. Три точки – это не оценка с погрешностью, так что последний знак в таблицах читайте как ориентир, а не как точность. Хосты обрабатывались последовательно.

Версии инструментов – штатные из репозитория каждой ОС, намеренно не выравнивались: цель была измерить конфигурацию из коробки. fio 3.28 / 3.36 / 3.41, OpenSSL 3.0.2 / 3.0.13 / 3.5.5. Для fio и sysbench разница версий на результат практически не влияет, для openssl – влияет, см. раздел с оговорками.

Диск

Профили – те же четыре, что в CrystalDiskMark: по факту они давно стали стандартом, и результаты легко сопоставить с любыми чужими замерами:

# тестовый файл – ОБЯЗАТЕЛЬНО на дисковом разделеTESTFILE=/var/tmp/fio_test# SEQ1M Q8T1 – потолок в идеальных условияхfio --name=seq1m_q8t1_read --filename=$TESTFILE --size=1G \    --rw=read --bs=1M --iodepth=8 --numjobs=1 \    --ioengine=libaio --direct=1 --runtime=30 --time_based \    --group_reporting# SEQ1M Q1T1 – копирование одного большого файлаfio --name=seq1m_q1t1_read --filename=$TESTFILE --size=1G \    --rw=read --bs=1M --iodepth=1 --numjobs=1 \    --ioengine=libaio --direct=1 --runtime=30 --time_based \    --group_reporting# RND4K Q32T1 – отзывчивость под нагрузкой (БД, много мелких файлов)fio --name=rnd4k_q32t1_read --filename=$TESTFILE --size=1G \    --rw=randread --bs=4k --iodepth=32 --numjobs=1 \    --ioengine=libaio --direct=1 --runtime=30 --time_based \    --group_reporting# RND4K Q1T1 – то же, но по одной операции за разfio --name=rnd4k_q1t1_read --filename=$TESTFILE --size=1G \    --rw=randread --bs=4k --iodepth=1 --numjobs=1 \    --ioengine=libaio --direct=1 --runtime=30 --time_based \    --group_reporting

Для записи – --rw=write и --rw=randwrite соответственно. Плюс отдельная контрольная серия ровно теми же командами, но с --size=6G – зачем, объясняю дальше.

CPU, память, крипто, архиватор

sysbench cpu --cpu-max-prime=20000 --threads=1 --time=30 runsysbench cpu --cpu-max-prime=20000 --threads=4 --time=30 runsysbench memory --memory-block-size=1M --memory-total-size=10G \         --memory-oper=read runsysbench memory --memory-block-size=1M --memory-total-size=10G \         --memory-oper=write runopenssl speed -seconds 10 -evp aes-256-cbcopenssl speed -seconds 10 sha2567z b

К слову openssl speed sha256 -seconds 10 падает с Unknown algorithm -seconds. В OpenSSL 3.x опции обязаны идти до имени алгоритма. Правильно будет openssl speed -seconds 10 sha256.

Три грабли

Раздел важный, потому что от него зависит, можно ли верить таблицам ниже. Каждая из ошибок не ломает тест и не выдаёт ничего похожего на сбой – она просто подменяет то, что вы измеряете, и возвращает вполне правдоподобное число. Заметить подмену по самому результату нельзя, только по методике – что я и сделал.

Грабля №1: /tmp – это не диск

Классическое место для тестового файла – /tmp. На SmartApe (Ubuntu 26.04) /tmp смонтирован как tmpfs размером 981 МБ, то есть лежит в оперативной памяти.

В предварительном прогоне я получил у SmartApe 2.5 ГБ/с – файл на 256 МБ помещался в tmpfs целиком, и fio измерил скорость RAM. Цифра абсолютно правдоподобная для NVMe. Я бы её опубликовал.

Проверка по всем пяти хостам:

Хост

/tmp

/var/tmp

SmartApe

tmpfs, 1 ГБ

ext4, 35 ГБ

IHC.host

ext4, 65 ГБ

ext4, 65 ГБ

Cloud4U

ext4, 11 ГБ

ext4, 11 ГБ

RUVDS

ext4, 35 ГБ

ext4, 35 ГБ

Reg.ru

ext4, 74 ГБ

ext4, 74 ГБ

Один хост из пяти. Причём именно тот, у которого ОС новее всех.

Тестовый файл переехал в /var/tmp (дисковый раздел на всех пяти), а в скрипт добавлена явная проверка – на tmpfs/ramfs дисковые тесты теперь отказываются стартовать с ошибкой, а не меряют память:

FSTYPE=$(stat -f -c %T "$(dirname "$TESTFILE")")case "$FSTYPE" in  tmpfs|ramfs)    echo "ОТКАЗ: $(dirname "$TESTFILE") – это $FSTYPE, тут вы измерите RAM" >&2    exit 1 ;;esac

Кто повторяет такие замеры – проверяйте stat -f -c %T /tmp до публикации, а не после.

Грабля №2: —direct=1 не отключает кэш гипервизора

Следите за руками.

--direct=1 в fio отключает страничный кэш внутри гостевой ОС. Кэширование на стороне хоста он не обходит, и изнутри ВМ отключить его невозможно в принципе. А тестовый файл на 1 ГБ целиком помещается в RAM хоста. Механизм такой: первое чтение идёт с носителя, а дальше файл целиком оседает в памяти физического хоста, и все последующие тесты в батарее читают уже оттуда. Вы думаете, что меряете диск, а меряете RAM чужого сервера.

Само по себе внутри одного прогона это не поймать: цифры выглядят естественно. Ловит только контроль на файле, который заметно крупнее – если результат на большом файле резко падает, значит на маленьком вы читали кэш. Поэтому основную батарею я оставил на 1 ГБ (чтобы результаты были сопоставимы между хостами), но добавил контрольную серию теми же командами на файле 6 ГБ.

Провайдер

SEQ1M Q8T1 чт., МБ/с

SEQ1M Q1T1 чт., МБ/с

RND4K Q32T1 чт., IOPS

RND4K Q1T1 чт., IOPS

SmartApe

5 387.2

1 379.4

107 062

6 440

IHC.host

2 947.1

1 013.3

152 516

8 095

Cloud4U

3 074.8

1 060.9

40 302

7 903

RUVDS

49.3 (29.9x)

49.2 (8.8x)

6 010 (7.9x)

1 297

Reg.ru

11 243.1

1 478.5

40 132

7 575

В скобках во сколько раз результат на файле 1 ГБ выше контрольного.

Две вещи, без которых таблицу можно прочитать неправильно.

  1. Контроль снят только по чтению – колонки записи в результатах не проверены ничем.

  2. У четырёх хостов из пяти расхождения нет (всё в диапазоне 0.7–1.02x), но это не значит, что цифры проверены. Совпадение исключает кэш меньше 6 ГБ и ничего не говорит про больший, а сколько памяти у хоста, изнутри ВМ не узнать. Тест асимметричен: падение результата – улика, а совпадение не оправдание.

У RUVDS расхождение кратное: последовательное чтение падает с 1 474.8 до 49.3 МБ/с (в 30 раз), случайное Q32 – с 47 510 до 6 010 IOPS. Красивые 1 474.8 МБ/с NVMe на большом файле оказались 49 МБ/с. Причём 49.3 при очереди 8 и 49.2 при очереди 1 – совпадение до 0.2% при восьмикратной разнице очереди, то есть это не скорость носителя, а полка лимитера, в которую упираешься после исчерпания бёрст-кредита.

Отдельно про Reg.ru, и тут честно – я не знаю. Контроль расхождения не выявил, но 10-11 ГБ/с последовательного чтения для рядового VPS-тарифа выглядят оптимистично, и объяснить их я не могу ни одним механизмом целиком. Кэш? За 30 секунд контрольного теста прочитано около 337 ГБ, то есть примерно 56 проходов по файлу в 6 ГБ, – на пятьдесят шестом проходе упреждающее чтение уже ни при чём, это похоже на резидентность. Но тогда rnd4k Q1 на той же машине должен летать, а он даёт 6 046 IOPS, то есть 132 мкс на операцию, – для чтения из оперативки хоста это непозволительно долго.

Две цифры указывают в разные стороны, и изнутри ВМ я их не развожу. Поэтому корректная формулировка такая: для последовательных колонок Reg.ru я не могу определить, что именно измерил. Это верхняя граница виртуального диска вместе со всем, что под ним кэширует, а не скорость носителя. Контроль на 6 ГБ тут не сработал – не потому, что цифры хорошие, а потому, что 6 ГБ для этого хоста оказалось мало.

Грабля №3: слишком ровные цифры – это лимитер

Казалось бы, если три прохода дали почти одинаковый результат – значит, стабильная площадка, ставим плюсик. Но неправдоподобная стабильность обычно означает, что вы упёрлись не в носитель, а в жёсткий QoS-лимит на стороне хранилища. У трёх хостов из пяти так и оказалось.

Хост

Похоже на лимит

Что за этим стоит

IHC.host

500 МиБ/с на запись

последовательная запись = ровно 526.0 МБ/с во всех шести замерах (Q8 и Q1, три прохода). 526.0 МБ/с – это 501.6 МиБ/с

Reg.ru

40 000 IOPS

rnd4k Q32 = 40 132.5–40 132.7 IOPS, разброс между проходами 0.001%. Контроль на 6 ГБ даёт 40 132 – ровно то же самое

Cloud4U

40 000 IOPS

rnd4k Q32: чтение 40 329, запись 40 327 – расхождение 0.005% между операциями совершенно разной природы. Контроль на 6 ГБ даёт 40 302, та же полка

Про Cloud4U стоит сказать отдельно, потому что тут признак другой, чем у Reg.ru. У Reg.ru улика – разброс между проходами: 0.001% на трёх повторах. У Cloud4U разброс в такой детализации я не смотрел, зато совпали чтение и запись. Это разные пути в стеке хранилища: чтение обязано сходить за данными, запись обслуживается write-back кэшем, и на живом носителе они дают разные числа – что видно по остальным хостам выборки (у SmartApe 103 851 против 54 693, почти вдвое). Совпадение до 0.005% означает, что обе операции упираются не в носитель, а в общий для них счётчик.

И отдельное наблюдение, которое я не могу объяснить, но обязан отметить: полка в районе 40 000 IOPS обнаружилась сразу у двоих из трёх – у Reg.ru (kvm) и у Cloud4U (vmware). Разные провайдеры, разные гипервизоры, разные ОС, а число одно. Похоже, 40k – это просто распространённая коммерческая ступень QoS, а не свойство какого-то конкретного железа. Если так, то встретить её вы можете где угодно, и это ещё один аргумент за то, чтобы проверять свои цифры на совпадения, а не радоваться их стабильности.


Результаты

Диск, файл 1 ГБ

Провайдер

Тип¹

SEQ1M Q8T1 чт.

SEQ1M Q8T1 зап.

SEQ1M Q1T1 чт.

SEQ1M Q1T1 зап.

SmartApe

NVMe

5 133.0

4 269.0

1 403.8

1 886.4

IHC.host

NVMe

2 768.9

526.0

1 032.4

526.0

Cloud4U

NVMe

2 222.3

738.1

817.2

555.2

RUVDS

NVMe

1 474.8

1 420.4

434.9

798.2

Reg.ru

NVMe

10 229.4

7 705.9

1 421.5

3 163.5

Значения – МБ/с. По RUVDS достоверна не отдельная цифра, а пара «бёрст ~1.4 ГБ/с → полка ~50 МБ/с после его исчерпания» – см. граблю №2.

Провайдер

Тип¹

RND4K Q32T1 чт.

RND4K Q32T1 зап.

RND4K Q1T1 чт.

RND4K Q1T1 зап.

SmartApe

NVMe

103 851

54 693

5 064

11 721

IHC.host

NVMe

126 076

127 760

6 416

18 476

Cloud4U

NVMe

40 329

40 327

5 513

14 241

RUVDS

NVMe

47 510

38 822

1 230

1 479

Reg.ru

NVMe

40 133

40 129

6 046

14 609

Значения – IOPS.

Про колонки записи. У всех пяти хостов запись при очереди 1 быстрее чтения – обычный признак write-back кэша: чтение обязано сходить за данными, а запись считается завершённой, как только её подтвердил кэш. Так что записи в таблицах – это скорее скорость подтверждения, чем гарантированная скорость на носителе.

Кроме уже разобранных лимитеров, тут стоит отметить одну связку. У IHC.host странно смотрится связка «126 тысяч IOPS на случайных операциях» и «526 МБ/с на последовательной записи». Первое – отличный результат, лучший в тесте на Q32-чтении (и 152 516 IOPS в контрольном замере на 6 ГБ). Второе – полка лимитера. Разные метрики упираются в разные ограничения, и это в целом нормально, просто не переносите одну на другую.

CPU и память

Провайдер

sysbench CPU 1 поток

sysbench CPU все ядра

Память чт., МиБ/с

Память зап., МиБ/с

SmartApe

341

1 353

19 321.0

15 151.1

IHC.host

363

1 449

18 951.5

15 428.9

Cloud4U

418

1 661

20 998.0

18 180.8

RUVDS

408

1 606

20 577.8

17 274.6

Reg.ru

911

3 642

21 708.4

20 046.3

CPU событий/с, больше лучше.

По sysbench Reg.ru (Icelake) даёт 911 событий/с в один поток против 341–418 у остальных и 3 642 на всех ядрах против 1 353–1 661; масштабирование у всех пяти линейное, ×4 к однопоточному.

Записывать это в «быстрый процессор» я бы не стал: другие счётные тесты отрыва не подтверждают. Относительно второй машины в каждом тесте Reg.ru впереди на 3% по 7-Zip (16 176 против 15 666 у RUVDS), на 14% по AES и на 3% по чтению из памяти – против 118% по sysbench. При этом 7-Zip и sysbench cpu оба целочисленные и оба грузят все ядра, так что расхождение в разы не спишешь ни на архитектуру (Icelake против Cascadelake – это проценты IPC, не разы), ни на соседей по гипервизору – те просадили бы и 7-Zip. Steal time я не снимал ни на одном хосте, поэтому назвать причину уверенно не могу; но аномалия тут скорее у метрики, чем у машины. По прикладной нагрузке – 7-Zip – все пятеро укладываются в 22%.

Остальное совпадает: разница между «Xeon Gold 6248 @ 2.50GHz» и «Xeon Processor (Cascadelake)» в названии не отражает ничего интересного, а по памяти разброс 18 951–21 708 МиБ/с – все пятеро в одной весовой категории.

Крипто и архиватор

Провайдер

AES-256-CBC, МБ/с²

SHA-256, МБ/с²

7-Zip, MIPS

SmartApe

824.3

340.1

14 171

IHC.host

758.9

345.7

13 235

Cloud4U

874.2

400.8

14 895

RUVDS

841.5

397.3

15 666

Reg.ru

996.4

1 050.2

16 176

На SHA-256 у Reg.ru отрыв выглядит совсем неприличным – 1 050 против 340–401. Но, полагаю, часть отрыва может давать не процессор, а версия OpenSSL. Их я намеренно не выравнивал, поэтому корректная интерпретация колонки – «производительность связки CPU + штатный OpenSSL этой ОС», а не «производительность CPU». Если вы соберёте одинаковый OpenSSL на всех пяти, разрыв уменьшится; насколько – вопрос нового исследования.

Аномалии и нестабильность

То, что не попало в медианы, но должно попасть в статью.

Хост

Метрика

Что произошло

SmartApe

seq1m_q8t1_write

разброс между проходами ×1.5 (4 269, 4 365, 2 901)

RUVDS

rnd4k_q32t1_write

разброс между проходами ×1.8 (38 822, 43 702, 24 126)

Одна из двух строк – у RUVDS. Вместе с кратным расхождением на контрольном замере это складывается в довольно последовательную картину: у этой конфигурации производительность заметно зависит от того, что творится вокруг и сколько вы уже успели прочитать.


Что можно утверждать, а что нет

Дальше идёт моя интерпретация. Выборка по одной машине на провайдера, снята в один заход, поэтому это утверждения про пять конкретных виртуалок. Но, тарифы у них разные. У SmartApe 1.9 ГБ RAM против 7.8 у трёх других, диски от 32 до 80 ГБ, цены я не нормировал. Так что ниже не привычный для восприятия «топ», а что может показать конкретная виртуалка на конкретном тарифе.

  • IHC.host – случайные операции. 152 516 IOPS на Q32 в контроле и лучший Q1 в выборке (8 095, то есть 124 мкс). Это самый прочный дисковый результат статьи: он и высокий, и не рассыпался на большом файле. Но есть потолок в 526 МБ/с на последовательной записи, и нагруженная запись в него упрётся. Оговорюсь, что 126 076 IOPS из основной таблицы – это те же 492 МиБ/с, подозрительно близко к потолку записи, так что часть Q32-результата может быть той же полкой, только в других единицах. Контрольные 152 516 (596 МиБ/с) её пробивают, значит на чтении лимит либо выше, либо другой.

  • Cloud4U – второй в выборке по Q1 (7 903 IOPS, 127 мкс), идёт вплотную за лидером. По последовательному чтению среди проверенных тоже второй (3 074.8 МБ/с на контроле). По счётной части в верхней половине: второй AES (874 МБ/с), третий 7-Zip (14 895, от лидера 9%). Но главное, единственная машина без строк в разделе аномалий. Потолок 40k на глубокой очереди у него есть, но это единственный хост, про который я могу точно сказать, где этот потолок проходит: 40 329 на чтении, 40 327 на записи, 40 302 в контроле.

  • SmartApe лучшее последовательное чтение из проверенных (5 387 МБ/с) и второй Q32 (107 062). Плюс единственный хост, у которого чтение и запись на Q32 расходятся вдвое (103 851 против 54 693) – по логике грабли №3 это признак живого носителя, а не общего счётчика, и полки я у него не нашёл ни одной. Из минусов – разброс ×1.5 на последовательной записи, худший Q1 из четвёрки (155 мкс) и tmpfs на /tmp меньше гигабайта, о который можно споткнуться далеко за пределами бенчмарков.

  • Reg.ru отличные память и 7-Zip, правда, с отрывом в 3%, то есть в пределах шума. Вообще по счётной нагрузке разброс между всеми пятью – 22% по 7-Zip, и на фоне дисковых расхождений в разы это не повод для выбора. Отдельно стоит SHA-256: 1 050 против 340–401 у остальных, но это связка «CPU + штатный OpenSSL», а не свойство машины, так что переносить эту цифру на выбор хостера я бы не стал. Также потолок 40k на глубокой очереди и последовательные числа, но ориентироваться на них при выборе я бы тоже не стал, выше уже объяснял почему.

  • RUVDS по счётной части претензий нет: второй 7-Zip (15 666 MIPS). По диску – 771 мкс на операцию при Q1 и полка ~50 МБ/с, в которую упирается и Q8, и Q1 (49.3 и 49.2 – совпадение до 0.2% при восьмикратной разнице очереди). Плюс обе строки раздела аномалий с разбросом ×1.5–1.8. Что именно даёт верхние цифры – бёрст-кредит или кэш хоста, – я не развёл: за 30 секунд теста на 1 474.8 МБ/с прочитано около 44 ГБ, и кредита такого объёма при полке 50 МБ/с не бывает, так что на кэш это похоже больше. Практический вывод одинаков в обоих случаях: эту машину надо мерить своей нагрузкой, а не бенчмарком, промежуточных состояний тут не видно.

И то, ради чего всё писалось

Дисковых чисел в этой статье сорок. Как минимум три из тех, что я собирался публиковать, оказались неправдой: 2.5 ГБ/с у SmartApe были скоростью RAM, 1 474.8 МБ/с у RUVDS – кэшем или бёрстом, но не носителем, «стабильные» 40 132 IOPS у Reg.ru – не диском, а конфигом лимитера. Все три выглядели совершенно нормально, и ни одну из них нельзя было опознать по самому результату – только по методике.


Оговорки

Тип носителя не измерен, а процитирован. Столбец «Тип диска» заполнен по заявлению провайдера. Изнутри гостевой ОС тип носителя не верифицируется: ни одного nvme*-устройства гость не видит ни на одном хосте, а флаг ROTA в виртуалках недостоверен – у части хостов он равен 1 (как у вращающегося диска), у части 0, притом что заявленный тип носителя у всех пяти одинаковый. То есть флаг не различает даже одинаковые конфигурации. Проверить можно самим:

lsblk -d -o NAME,ROTA,MODELls /dev/nvme* 2>/dev/null || echo "nvme-устройств не видно"

Меряется виртуальный диск, а не носитель. Все диски виртуальные (virtio / QEMU / VMware / Hyper-V). Результаты отражают производительность виртуального диска так, как её видит гостевая ОС, включая накладные расходы виртуализации.

--direct=1 не отключает кэш гипервизора. Флаг обходит кэш только внутри гостя; на стороне хоста изнутри ВМ его не отключить. Контроль на большем файле необходим, но недостаточен.

Маленький вывод

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

Также, если у вас есть машины у этих же или других провайдеров – прогоните команды из раздела «Методика» и киньте цифры в комментарии, особенно контроль на 6 ГБ. Мне сильно интереснее собрать выборку больше одной машины на хостера, чем защищать текущую таблицу.

И главное, ради чего всё писалось: перед публикацией любых дисковых замеров с VPS сделайте три вещи – проверьте stat -f -c %T на каталоге с тестовым файлом, повторите тест на файле, заметно превышающем вашу собственную RAM (и помните, что даже это не гарантирует выход за пределы кэша хоста – его объём вам неизвестен), и посмотрите на разброс между проходами. Работы немного, зато вы хотя бы будете знать, чего ваши цифры не доказывают.

ссылка на оригинал статьи https://habr.com/ru/articles/1066584/