Як правильно протестувати VPS: yabs.sh, fio, sysbench
Запустіть yabs.sh, а потім fio, sysbench та iperf3 вручну: пояснюємо значення результатів і чому один тест VPS майже нічого не доводить.
Що означає бенчмаркінг VPS
Під час бенчмаркінгу VPS вимірюють чотири показники: швидкість роботи одного ядра CPU, пропускну здатність пам’яті, кількість малих довільних операцій диска, які сховище виконує за секунду, і пропускну здатність мережевого каналу. Один запуск yabs.sh приблизно за десять хвилин дає результати для CPU, диска та мережі; для вимірювання пропускної здатності пам’яті використовуйте окремий тест нижче. Важче правильно інтерпретувати результат, оскільки VPS (віртуальний приватний сервер) використовує фізичне обладнання спільно з іншими орендарями. Тому на одному й тому самому сервері о 03:00 може бути один результат, а о 20:00 — зовсім інший.
Спочатку запустіть yabs.sh для швидкої оцінки, а потім вручну виконайте інструменти, які він використовує. Самостійний запуск дає змогу змінити один прапорець, простежити, як змінюється результат, і зрозуміти, що саме вимірює цей показник. Виконуйте це після налаштування сервера, а не до нього. Спочатку виконайте кроки з розділу перші десять хвилин на новому VPS, оскільки сервер, на якому ще встановлюється перший набір оновлень, покаже низькі результати бенчмаркінгу з причин, не пов’язаних з обладнанням.
Подивіться на машину, перш ніж її вимірювати
Половина кожного невдалого бенчмарку — це машина, особливостей якої автор не розумів.
nproc
lscpu | grep -E 'Model name|Hypervisor|Thread'
free -h
df -hT /
uname -r
systemd-detect-virtHypervisor vendor: KVM означає повну віртуалізацію, тому ви запускаєте власне ядро. Виведення systemd-detect-virt lxc або openvz означає контейнерну віртуалізацію: ви спільно використовуєте ядро хоста, а обмеження CPU та пам’яті задаються параметрами cgroup (control group), а не віртуальним обладнанням. У системі з cgroup v2 ліміт CPU можна прочитати з cgroup контейнера; наведений нижче шлях застосовується, якщо цю cgroup змонтовано в /sys/fs/cgroup.
cat /sys/fs/cgroup/cpu.maxmax 100000 означає, що ця cgroup не має власної квоти; батьківські cgroup все одно можуть її встановлювати. 200000 100000 означає, що можна використовувати 200000 мікросекунд CPU протягом кожного періоду тривалістю 100000 мікросекунд, тобто квоту, еквівалентну двом ядрам. План, заявлений як 4 vCPU, але з квотою у два ядра, ніколи не покаже результат на рівні чотирьох ядер. Інструменти для бенчмарків можуть виявити це обмеження: VoxelBench показує квоти CPU та позначає спільний або обмежений за пропускною здатністю CPU, якщо хост надає значно більше CPU, ніж сервер може використовувати.
df -hT / важливе з іншої причини: стовпця Type. Якщо в ньому зазначено overlay, ви перебуваєте всередині контейнера, а результати тестування диска описуватимуть сховище, розташоване під цим overlay. Зафіксуйте це зараз.
Постійно контролюйте steal time
Steal time — це частка часу, протягом якого ваша віртуальна CPU очікувала без можливості виконання, оскільки hypervisor не запланував її виконання. Це корисний індикатор недоступного процесорного часу, але він не розрізняє зайнятих сусідів і застосування провайдером вашої CPU quota.
vmstat 1 10Праворуч переглядайте стовпчик st. Тривалий steal time означає, що guest не мав доступу до процесорного часу, але значення понад 5% не доводить oversubscription хоста. Провайдери можуть навмисно показувати застосування CPU quota як steal time. top відображає те саме значення, що й %st у рядку CPU. Під час benchmark залишайте vmstat 1 запущеним у другій SSH-сесії та записуйте значення steal поруч із кожним результатом.
Почніть із yabs.sh
yabs.sh (Yet Another Bench Script) — це shell-скрипт, який запускає fio, iperf3 і Geekbench та виводить один підсумковий звіт. Якщо fio та iperf3 уже встановлені, скрипт використовує їх. Якщо ні, він завантажує статичні бінарні файли. У обговореннях результатів тестування VPS це стандартний формат, тому вивід yabs — найшвидший спосіб порівняти результати з іншими.
Ось однорядкова команда з офіційного проєкту.
curl -sL yabs.sh | bashВона передає все, що URL повертає на цей момент, безпосередньо в shell. Спочатку завантажте скрипт і прочитайте його. Потім запустіть.
curl -sLo yabs.sh https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh
less yabs.sh
bash yabs.shЯкщо використовуєте pipe, прапори потрібно вказувати після -s --. Якщо запускаєте локальну копію, прапори вказують одразу після імені файлу. Корисні прапори: -f пропускає тест диска, -i пропускає тест мережі, -g пропускає Geekbench, -r скорочує кількість локацій iperf3 до трьох, -j виводить результати у форматі JSON, а -w results.json записує цей JSON у файл.
bash yabs.sh -r -w yabs-run1.jsonПеред першим запуском потрібно знати дві речі. Geekbench завантажує результати та виводить загальнодоступний URL на browser.geekbench.com. Будь-хто, хто має це посилання, може переглянути модель вашого CPU та результати тестів. Прапор -g повністю пропускає цей тест. По-друге, на етапі тестування iperf3 передається реальний мережевий трафік до серверів у кількох регіонах. Цей трафік враховується у вашому щомісячному ліміті. На каналі зі швидкістю 1 Gbit/s повний мережевий тест може передати десятки гігабайт. Тому за малого ліміту використовуйте -r, а на тарифі з оплатою за обсяг трафіку — -i.
Що означає кожна частина виводу yabs
Розділ диска запускає fio зі співвідношенням читання та запису 50/50 для чотирьох розмірів блоків: 4k, 64k, 512k і 1m. Для кожного розміру він показує IOPS (операції вводу-виводу за секунду) і пропускну здатність. Для бази даних, поштового сервера або будь-якого сервісу, який виконує багато малих операцій запису, важливий рядок 4k, оскільки більшість серверних операцій вводу-виводу мають малий і розрізнений характер. Рядок 1m важливий для резервного копіювання та роботи з відео, коли передаються довгі послідовності байтів.
Розділ мережі запускає iperf3 проти публічних серверів у кількох регіонах і перевіряє передавання в обох напрямках із використанням паралельних потоків. Сприймайте низький показник як привід для додаткової перевірки, а не як остаточний висновок, оскільки публічні сервери iperf3 є спільними для багатьох користувачів і часто перевантажені. Тому низький результат може бути спричинений віддаленою стороною.
Розділ Geekbench містить оцінку продуктивності одного ядра та оцінку багатоядерної продуктивності. Показник одного ядра прогнозує, як швидко завершиться один запит, одна компіляція або один запит до бази даних. Багатоядерний показник переважно показує, скільки ядер ви фактично отримали.
Disk: запустіть fio самостійно
fio (flexible IO tester) — це інструмент, який використовується в розділі дискових тестів yabs. Якщо запускати його безпосередньо, параметри починають мати практичне значення.
sudo apt update && sudo apt install -y fio sysbench iperf3Тест випадкового читання блоками 4k із глибиною черги 32 у файловій системі, яка вас фактично цікавить:
fio --name=randread4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randread --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reportingРядок підсумку, який потрібно знайти у виводі, має такий вигляд.
read: IOPS=184k, BW=719MiB/s (754MB/s)(42.1GiB/60001msec)Після нього fio виводить блок clat percentiles. Варто наводити значення 99.00-го перцентиля, оскільки воно показує, скільки чекало найдовше одне з кожних ста запитів. Середня затримка приховує саме ті затримки, які помічає користувач.
--direct=1відкриває файл із параметромO_DIRECT, тому читання обходить кеш сторінок ядра. Без цього повторне читання файлу розміром 2G на машині з 8G оперативної пам’яті обслуговується з пам’яті, а fio показує мільйони IOPS. Це значення реальне, але воно характеризує пам’ять.--ioengine=libaioнадсилає асинхронні запити. Саме це дає змогу--iodepth=32одночасно обробляти 32 запити. Із синхронним рушієм, таким якpsync, значення iodepth понад 1 нічого не змінює, тому вимірюється лише один запит за раз.--time_based --runtime=60запускає тест на фіксовані 60 секунд, а не на фіксований обсяг роботи. Тому швидкий і повільний диски працюють однаковий час, а порівняння залишається коректним.--size=2Gзадає розмір тестового файлу. Він має бути більшим за будь-який кеш у ланцюжку обробки. Спочатку перевірте, чи достатньо вільного місця.
Для випадкового запису використовуйте ту саму команду з --rw=randwrite. Запустіть тест окремо, а потім видаліть файл.
fio --name=randwrite4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randwrite --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reporting
rm -f ./fio-testfileДля суміші операцій, ближчої до реального мережевого навантаження, використовуйте --rw=randrw --rwmixread=70. Тип сховища, на якому працює система, впливає на ці результати сильніше, ніж будь-який параметр. Цю відмінність розглянуто в матеріалі про різницю між NVMe та SATA SSD у VPS.
Коли fio завершується з помилкою Unknown error -1
Direct IO доступний не в кожній файловій системі. Тому, якщо fio завершує свій перший запит із параметром --direct=1, спочатку потрібно виключити проблему з direct IO. Помилка може мати такий вигляд:
fio: io_u error on file ./fio-testfile: Unknown error -1: read offset=0, buflen=4096
fio: pid=1234, err=-1/file:ioengines.c:321, func=get_events, error=Unknown error -1Спочатку виконайте df -hT .. Type типу overlay, яку Docker за замовчуванням надає контейнеру, сама по собі не є причиною проблеми. overlayfs передає O_DIRECT до базової файлової системи та відхиляє його лише тоді, коли ця файлова система не підтримує direct IO. Тому --direct=1 --ioengine=libaio працює в overlayfs поверх ext4 або xfs. Якщо файлова система під тестовим файлом справді не підтримує direct IO, fio зазвичай повідомляє про це під час відкриття файла: fio: looks like your file system does not support direct=1/buffered=0. У такому разі вкажіть --filename шлях на реальне локальне сховище, наприклад на bind mounted volume, або запустіть fio на host замість контейнера. Якщо доступу до реального сховища немає, buffered synchronous запуск принаймні підтвердить, що сама команда правильна.
fio --name=randread4k-buffered --filename=./fio-testfile --size=256M --bs=4k \
--rw=randread --ioengine=psync --direct=0 --numjobs=1 \
--runtime=15 --time_based --group_reporting
rm -f ./fio-testfileЧітко визначте призначення цього запуску. Після першого проходу файл розміром 256M залишається в page cache, тому показник IOPS описує швидкодію вашої RAM. Використовуйте цей запуск, щоб перевірити, що fio встановлено, а параметри коректно розбираються. Не наводьте цей результат як показник швидкодії диска.
Чому dd не є тестом продуктивності диска
dd часто згадують у темах про VPS, але ця команда дає відповідь лише на одне вузьке питання.
dd if=/dev/zero of=./ddtest bs=1M count=1024 oflag=direct conv=fdatasync
rm -f ./ddtestВона вимірює послідовну швидкість запису в одному потоці, коли одночасно виконується один запит. Це прийнятна базова перевірка. Вона нічого не говорить про довільний доступ до даних і про те, що станеться, коли одночасно надійдуть 32 запити. Якщо прибрати oflag=direct, операції запису проходитимуть через page cache, але conv=fdatasync усе одно змушує записати вихідні дані на сховище до завершення команди. Якщо прибрати і цей параметр, результат переважно показуватиме, наскільки швидко ядро приймає операції запису в пам’ять. Саме тому значення dd, які наводять у дописах на форумах, часто є нереалістично високими.
CPU: sysbench cpu
sysbench cpu --cpu-max-prime=20000 --threads=1 run
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) runОрієнтуйтеся на показник events per second. Спочатку запустіть тест в одному потоці. Це показник, який визначає, наскільки швидко завершується один PHP-запит або одна операція компіляції. Він найбільше відрізняється між хостами однакової вартості. Потім запустіть тест з усіма потоками. Це покаже, як масштабується пропускна здатність на виділених вам vCPU.
Чітко розумійте, що саме вимірює цей тест: sysbench cpu багаторазово знаходить прості числа методом пробного ділення. Для кожного кандидата він обчислює квадратний корінь подвійної точності, а потім перевіряє дільники за допомогою операції modulo над 64-бітними цілими числами, порівнюючи кожен дільник з межею у форматі з плаваючою комою. Отже, тест поєднує операції над цілими числами та числами з плаваючою комою. Він не створює навантаження на пропускну здатність пам’яті, векторні блоки або кеш так, як це робить реальне робоче навантаження. Тому він підходить для порівняння двох хостів, але погано прогнозує роботу вашого застосунку.
Ubuntu 24.04 постачається із sysbench 1.0.20, де назва тесту вказується першою. Якщо скопіювати команду з --test=cpu зі старого допису, ви отримаєте WARNING: the --test option is deprecated. Результати sysbench 0.4 і sysbench 1.0 взагалі не можна порівнювати. Тому ніколи не порівнюйте власний результат з опублікованим числом, якщо для нього не вказано версію.
Пам’ять: sysbench memory
sysbench memory --memory-block-size=1M --memory-total-size=20G --memory-oper=write --threads=1 run
sysbench memory --memory-block-size=1M --memory-total-size=20G --memory-oper=read --threads=1 runРезультат наведено в MiB/sec. Залишайте --memory-block-size рівним 1M і використовуйте це саме значення на кожному хості, який порівнюєте. За значення 1K результат різко погіршується, оскільки накладні витрати на кожну операцію виникають у тисячу разів частіше. У підсумку ви вимірюєте вартість циклу, а не пропускну здатність пам’яті. Це прапорець, значення якого найчастіше відрізняється в опублікованих результатах тестування пам’яті.
Мережа: iperf3
Коректний спосіб перевірити пропускну здатність — виконати тест на другій машині, якою ви керуєте. Тоді ви знаєте, що відбувається на обох кінцях з’єднання.
На віддаленій машині:
iperf3 -sЦя команда прослуховує TCP-порт 5201. Відкрийте порт лише для адреси, з якої виконуєте тест, і закрийте його після завершення. У розділі Базові правила брандмауера ufw на VPS описано відповідний синтаксис.
На VPS, який тестуєте:
iperf3 -c 203.0.113.10 -t 30
iperf3 -c 203.0.113.10 -t 30 -R
iperf3 -c 203.0.113.10 -t 30 -P 8Перша команда вимірює вихідну швидкість із машини, яку тестуєте. -R змінює напрямок і вимірює вхідну швидкість. -P 8 відкриває вісім паралельних потоків.
Виконайте тест як з одним потоком, так і в паралельному режимі. Ці результати відповідають на різні запитання. Одне TCP-з’єднання може передати лише такий обсяг непідтверджених даних, який дозволяє його вікно. Тому його гранична швидкість приблизно дорівнює розміру вікна, поділеному на час проходження сигналу туди й назад. За затримки 80 ms і вікна 4 MB ця межа становить приблизно 400 Mbit/s, незалежно від фактичної швидкості каналу. Показник для одного потоку показує, яку швидкість отримає одне завантаження. Показник для паралельних потоків показує пропускну здатність каналу.
Під час тестування стежте за доступним обсягом трафіку. За 30 секунд на швидкості 1 Gbit/s передається приблизно 3.75 GB, а тест потрібно буде виконати кілька разів у кожному напрямку.
Еталонні значення та інтерпретація ваших результатів
Дані, на яких побудовано графік
[
{
"device": "Local NVMe",
"iops_4k_read": "180,000"
},
{
"device": "Local SATA SSD",
"iops_4k_read": "90,000"
},
{
"device": "Network block",
"iops_4k_read": "12,000"
},
{
"device": "Spinning disk",
"iops_4k_read": "180"
}
]У опублікованих результатах локальний NVMe-том зазвичай показує близько 180,000 IOPS для випадкового читання блоками 4k. Для локального SATA SSD цей показник становить приблизно 90,000. Мережеве блочне сховище, де кожен запит проходить через мережу, перш ніж досягти диска, зазвичай показує близько 12,000, а HDD із обертовими дисками забезпечує приблизно 180, оскільки для кожного випадкового запиту переміщує фізичну головку.
Це типові опубліковані значення для кожного класу сховищ, а не результати вимірювань на одному хості. Використовуйте їх лише для однієї мети: перевірити, чи ваш результат перебуває в тому самому порядку величини. Якщо план, заявлений як NVMe, показує під час тестування лише кілька тисяч IOPS для випадкового читання блоками 4k, спочатку переконайтеся, що --direct=1 було ввімкнено. Якщо так, перевірте ліміти IOPS і burst credits плану, а також конкуренцію за сховище та заявлене обладнання.
Чому один запуск не є бенчмарком
Один результат — це знімок однієї хвилини на спільній машині. Розглядайте його як один зразок.
- Запускайте кожен тест щонайменше п’ять разів у різні години та щонайменше у два різні дні. Зберігайте медіану та розкид. Результат без розкиду — це маркетинговий показник.
- Записуйте steal time поруч із кожним запуском. Зберігайте запуски, під час яких
stбув високим, і з’ясовуйте, чи відображають вони конкуренцію за ресурси або CPU quota плану; вилучення таких результатів може приховати фактичну продуктивність, яку ви отримуєте. - Запускайте disk test з двома значеннями тривалості. Багато планів надають burst IOPS allowance, який з часом відновлюється, але ні 60-секундний запуск fio, ні
--runtime=600не гарантують, що ви виміряли мінімальний рівень продуктивності. AWS gp2 може підтримувати 3,000 IOPS щонайменше 30 хвилин із повного балансу, тому обидва запуски можуть вимірювати burst performance. Перевірте модель credit у провайдера та стежте за credit balance, перш ніж називати результат сталою продуктивністю. - Переконайтеся, що більше нічого не запущено.
unattended-upgrades, який запускає apt transaction посеред CPU test, знижує фактичний результат, аps -e -o comm= | grep -E 'apt|dpkg'перед кожним запуском займає секунду. - Змінюйте лише одну змінну за раз. Різні версії інструментів, block size або кількість потоків дають числа, які не можна порівнювати, хоч би наскільки схожими вони здавалися.
Порівнюючи двох провайдерів, запускайте тести в одну й ту саму годину одного й того самого дня. Інакше ви виміряли час доби.
Оцінюйте власне робоче навантаження в останню чергу
Синтетичні інструменти ранжують сервери. Лише власне робоче навантаження показує, чи достатньо продуктивності сервера. Вимірюйте час саме тієї операції, яку ви фактично виконуєте.
time tar -czf /tmp/bench.tgz /usr/share
rm -f /tmp/bench.tgzЦя операція стискає кілька сотень мегабайтів, тому одночасно навантажує CPU і диск. Результат змінюється, якщо змінюється будь-який із них. Попередження Removing leading / from member names є нормальним. Ще краще виміряти час власної збірки, власного найповільнішого запиту або рендерингу власної сторінки. Якщо збірка триває 4 хвилини на одному хості та 7 хвилин на іншому, це остаточно відповідає на запитання незалежно від оцінки Geekbench. Саме це вимірювання показує, з якого моменту додаткова продуктивність сервера вже не виправдовує витрати. Це варто знати до того, як ви прочитаєте скільки насправді коштує VPS на місяць або перенесете робоче навантаження на виділений сервер.
FAQ
Чому я щоразу отримую інший результат тесту?
VPS використовує фізичний CPU, сховище й мережу спільно з іншими орендарями, тому результат залежить від того, що вони роблять у цей момент. Під час тесту запустіть vmstat 1 і перегляньте стовпець st: стабільний steal time показує недоступний час CPU, але він може бути наслідком як обмеження провайдером придбаної вами частки CPU, так і конкуренції за ресурси хоста. Значення понад 5% саме по собі не встановлює причину. Важливий метод, а не точкове налаштування. Запустіть кожен тест щонайменше п’ять разів у різні години, а потім наведіть медіану разом із розкидом результатів.
Чому fio показує мільйони IOPS?
Майже завжди тому, що відсутній --direct=1. Без нього fio читає через page cache ядра, тому після першого проходу тестовий файл розміром 2G обслуговується з RAM, і ви вимірюєте пропускну здатність пам’яті. Додайте --direct=1 і зробіть тестовий файл більшим за будь-який cache на цьому шляху. Якщо після цього --direct=1 завершується помилкою, виконайте df -hT . і перевірте, на якому сховищі розташований тестовий файл. Тип overlay сам по собі не є проблемою, оскільки overlayfs передає O_DIRECT до нижнього сховища. Переміщуйте тестовий файл на реальне локальне сховище лише тоді, коли нижня файлова система не підтримує direct IO.
Чи достатньо yabs.sh без додаткових інструментів?
Для первинної оцінки — так. Він запускає fio з чотирма розмірами блоків, iperf3 в обох напрямках і Geekbench, а також виводить один підсумок, який можуть прочитати інші користувачі. Цього недостатньо, коли потрібно зрозуміти причину конкретного показника, оскільки його flags не можна змінювати окремо для кожного тесту. Якщо результат yabs здається неправильним, відтворіть його безпосередньо за допомогою fio або sysbench і змінюйте лише один flag за раз.
Яке одне число найкраще прогнозує швидкодію мого застосунку?
Для більшості web- і database-навантажень — швидкість одного core CPU і latency випадкового читання 4k, саме в такому порядку. Показники throughput виглядають переконливо, але рідко щось визначають, оскільки типовий запит невеликий. Наводьте 99-й перцентиль із блоку clat percentiles у fio, а не середнє значення, оскільки саме повільний один запит зі ста помічає користувач.
Чи потрібно щось інсталювати перед тестуванням?
fio, sysbench та iperf3 доступні в репозиторіях Ubuntu і Debian: sudo apt install -y fio sysbench iperf3. yabs.sh працює в Bash і потребує curl або wget для завантажень, а також tar для розпакування Geekbench; без tar він пропускає Geekbench. Якщо fio та iperf3 інстальовані, скрипт використовує їх, а якщо ні — завантажує статичні binaries. Після завершення видаліть усі тестові файли, оскільки залишений на диску обсягом 20G файл fio розміром 2G через кілька тижнів може спричинити alert про заповнення диска.