Как правильно протестировать производительность VPS
Узнайте, как объективно оценить мощность VPS с помощью yabs.sh, fio, sysbench и iperf3. Мы объясняем, почему разовый тест неинформативен и как учитывать влияние соседей по серверу.
Что означает бенчмаркинг VPS
Бенчмаркинг VPS подразумевает измерение четырех показателей: скорости работы одного ядра CPU, пропускной способности оперативной памяти, количества операций ввода-вывода (IOPS) при случайном доступе к диску и пропускной способности сетевого канала. Один запуск yabs.sh позволяет получить все четыре значения примерно за 10 минут. Интерпретация результатов — более сложная задача, так как 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 можно считать напрямую.
cat /sys/fs/cgroup/cpu.maxmax 100000 означает отсутствие квоты. 200000 100000 означает, что вы можете использовать 200000 микросекунд процессорного времени на каждые 100000 микросекунд периода, что соответствует квоте в два ядра. Тариф, заявленный как 4 vCPU с квотой в два ядра, никогда не покажет производительность четырех ядер, и ни одна утилита для бенчмаркинга не выведет сообщение с объяснением причины.
df -hT / важен по другой причине: из-за столбца Type. Если там указано overlay, вы находитесь внутри контейнера, и для теста диска ниже потребуются изменения. Зафиксируйте это сейчас.
Мониторинг steal time в реальном времени
Steal time — это доля времени, в течение которого ваш виртуальный процессор был готов к выполнению задач, но гипервизор отдал физическое ядро другому пользователю. Это самый информативный показатель того, что результат зависит от «соседей» по серверу, а не от производительности вашего оборудования.
vmstat 1 10Следите за столбцом st в правой части экрана. Стабильные значения 0 или 1 являются нормой. Постоянные значения выше 5 означают, что хост в данный момент перегружен, поэтому все показатели производительности процессора, зафиксированные в этот период, будут занижены не по вине вашей системы. В top отображается то же значение, что и в %st на строке CPU. Запустите vmstat 1 во втором SSH-сеансе во время проведения тестов и записывайте значение steal рядом с каждым результатом.
Начало работы с yabs.sh
yabs.sh (Yet Another Bench Script) — это shell-скрипт, который загружает статические бинарные файлы fio, iperf3 и Geekbench, выполняет их и выводит сводный отчет. Это общепринятый стандарт для обсуждения производительности 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Флаги указываются после -s -- при передаче через конвейер или сразу после имени файла при запуске локальной копии. Полезные флаги: -f пропускает тест диска, -i пропускает сетевой тест, -g пропускает Geekbench, -r сокращает количество локаций iperf3 до двух, -j выводит результаты в формате JSON, а -w results.json записывает этот JSON в файл.
bash yabs.sh -r -w yabs-run1.jsonПеред первым запуском необходимо учесть два момента. Geekbench загружает ваш результат и выводит публичную ссылку на browser.geekbench.com, поэтому любой, у кого есть эта ссылка, сможет увидеть модель вашего процессора и баллы. -g полностью пропускает этот тест. Во-вторых, этап iperf3 генерирует реальный трафик к серверам в различных регионах, что расходует ваш месячный лимит пропускной способности. На канале 1 Gbit/s полный сетевой тест может передать десятки гигабайт, поэтому используйте -r при небольшом лимите и -i на тарифах с оплатой за трафик.
Что означают показатели вывода yabs
В разделе disk запускается утилита fio с соотношением чтения и записи 50/50 для четырех размеров блоков: 4k, 64k, 512k и 1m. Для каждого из них отображаются IOPS (количество операций ввода-вывода в секунду) и пропускная способность. Строка 4k наиболее важна для баз данных, почтовых серверов и любых других задач с большим количеством мелких операций записи, так как основная часть серверного ввода-вывода состоит из небольших разрозненных блоков. Строка 1m актуальна для резервного копирования и работы с видео, где передаются значительные объемы данных.
В разделе network выполняется тестирование iperf3 с публичными серверами в различных регионах в обоих направлениях с использованием параллельных потоков. Низкие показатели здесь следует воспринимать как повод для проверки, а не как окончательный результат, так как публичные серверы iperf3 являются общими и часто перегружены, поэтому низкая скорость может быть вызвана проблемами на стороне удаленного узла.
Раздел Geekbench содержит оценки производительности для одного ядра и для многоядерного режима. Оценка для одного ядра показывает скорость выполнения одиночного запроса, компиляции или выполнения команды. Многоядерная оценка в основном отражает реальное количество доступных ядер процессора.
Диск: самостоятельный запуск 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) доступен не во всех файловых системах. overlay, файловая система, которую Docker предоставляет контейнеру по умолчанию, и некоторые сетевые файловые системы не поддерживают O_DIRECT, поэтому libaio отправляет запрос, который ядро не может выполнить, и fio прекращает работу:
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, укажите --filename путь к реальному хранилищу, например, к bind-монтируемому тому, или запустите fio на хосте вместо контейнера. Если доступ к реальному хранилищу невозможен, буферизованный синхронный запуск по крайней мере подтвердит корректность самой команды.
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 будет характеризовать вашу оперативную память. Используйте этот метод, чтобы убедиться, что fio установлена и флаги интерпретируются верно. Никогда не приводите эти данные как результат тестирования диска.
Почему dd не является инструментом для тестирования производительности диска
dd часто встречается в обсуждениях VPS, но этот инструмент отвечает лишь на один узкий вопрос.
dd if=/dev/zero of=./ddtest bs=1M count=1024 oflag=direct conv=fdatasync
rm -f ./ddtestЭта команда измеряет пропускную способность последовательной записи в один поток с одним запросом в очереди. Это приемлемая базовая проверка работоспособности. Она ничего не говорит о случайном вводе-выводе (random IO) и о том, что произойдет при одновременном поступлении 32 запросов. Если убрать oflag=direct, то команда в основном измеряет скорость, с которой ядро принимает данные на запись в оперативную память. Именно поэтому показатели 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 многократно находит простые числа, используя 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/сек, при этом на любой машине скорость чтения выше скорости записи. Оставляйте --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Первая команда измеряет скорость передачи данных (upload) с тестируемой машины. Флаг -R меняет направление, что позволяет измерить скорость загрузки (download). Флаг -P 8 открывает восемь параллельных потоков.
Запускайте как одиночный поток, так и параллельную версию, так как они отвечают на разные вопросы. Одно TCP-соединение может удерживать лишь столько неподтвержденных данных, сколько позволяет его окно, поэтому его предел примерно равен размеру окна, деленному на время кругового обхода (RTT). При задержке 80 мс и окне 4 MB этот предел составляет около 400 Mbit/s, независимо от реальной скорости канала. Показатель одиночного потока говорит о том, какую скорость получит одна загрузка. Параллельный показатель говорит о полной емкости канала.
Следите за лимитом трафика во время тестирования. Тридцать секунд на скорости 1 Gbit/s передают около 3.75 GB, а вы будете запускать тест несколько раз в каждом направлении.
Эталонные показатели и их интерпретация
The data behind this chart
[
{
"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, а обычный жесткий диск выдает примерно 180, так как для каждого случайного запроса требуется физическое перемещение считывающей головки.
Это типичные заявленные показатели для каждого класса хранилищ, а не измерения на одном конкретном хосте. Используйте их только для одной цели: проверки того, что ваш собственный результат находится в верном порядке величин. Если тариф, продаваемый как NVMe, показывает в тестах производительности низкие тысячи IOPS для 4k, сначала убедитесь, что --direct=1 был включен. Если это так, то либо хранилище не соответствует описанию на странице продукта, либо вы используете его совместно с очень активным «соседом» по серверу.
Почему один запуск не является бенчмарком
Единичный результат — это моментальный снимок состояния системы в конкретную минуту на разделяемом оборудовании. Рассматривайте его как одну выборку.
- Выполняйте каждый тест не менее пяти раз в разное время суток и как минимум в течение двух разных дней. Фиксируйте медиану и разброс значений. Результат, опубликованный без указания разброса, является маркетинговым показателем.
- Записывайте время ожидания (steal time) для каждого запуска. Отбрасывайте результаты, при которых
stбыло высоким, или, как минимум, отмечайте этот факт. - Проводите дисковый тест с двумя разными длительностями. Многие тарифные планы предоставляют лимит burst IOPS, который восстанавливается со временем, поэтому 60-секундный запуск fio измеряет пиковую производительность, в то время как
--runtime=600измеряет базовый уровень. Базовый уровень — это то, что вы получите в худший день. - Убедитесь, что никакие другие процессы не запущены.
unattended-upgrades, запускающий транзакцию apt в середине процессорного теста, искажает результаты, аps -e -o comm= | grep -E 'apt|dpkg'перед каждым запуском занимает секунду. - Изменяйте только одну переменную за раз. Разные версии инструментов, размеры блоков или количество потоков дают числа, которые нельзя сравнивать, независимо от того, насколько похожими они выглядят.
При сравнении двух провайдеров проводите тесты в один и тот же час одного и того же дня. В противном случае вы измеряете не производительность, а время суток.
Тестируйте собственную нагрузку в последнюю очередь
Синтетические инструменты ранжируют машины. Только ваша собственная рабочая нагрузка покажет, достаточно ли производительности сервера. Замеряйте время выполнения тех задач, которые вы решаете на самом деле.
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 постоянно выше 5, значит, хост перегружен, и низкий показатель CPU обусловлен внешними причинами. Решение заключается в методологии, а не в настройке. Выполняйте каждый тест пять и более раз в разное время суток, а затем фиксируйте медианное значение вместе с разбросом.
Почему fio показывает миллионы IOPS?
Почти всегда из-за отсутствия --direct=1. Без этого параметра fio читает данные через page cache ядра, поэтому после первого прохода тестовый файл размером 2G отдается из оперативной памяти, и вы измеряете пропускную способность RAM. Добавьте --direct=1 и следите, чтобы размер тестового файла превышал объем любого кэша на пути данных. Если после этого --direct=1 завершается с ошибкой err=-1/file:ioengines.c:321, func=get_events, error=Unknown error -1, выполните df -hT .: Type типа overlay не поддерживает O_DIRECT, поэтому направьте тест на реальный накопитель.
Достаточно ли одного yabs.sh?
Для первичной оценки — да. Скрипт запускает fio с четырьмя размерами блоков, iperf3 в обоих направлениях и Geekbench, выводя сводный отчет, понятный другим пользователям. Его становится недостаточно, когда нужно понять причины конкретных цифр, так как вы не можете менять флаги для каждого теста отдельно. Если результат yabs выглядит некорректно, воспроизведите его напрямую через fio или sysbench, изменяя по одному флагу за раз.
Какое число лучше всего предсказывает отзывчивость приложения?
Скорость одного ядра CPU и задержка при случайном чтении блоками 4k — именно в таком порядке для большинства веб-приложений и баз данных. Показатели пропускной способности выглядят внушительно, но редко на что-то влияют, так как типичный запрос имеет малый объем. Ориентируйтесь на 99-й перцентиль из блока clat percentiles в выводе fio, а не на среднее значение, так как пользователь замечает именно тот самый медленный запрос из сотни.
Нужно ли что-то устанавливать перед тестированием?
fio, sysbench и iperf3 есть в репозиториях Ubuntu и Debian: sudo apt install -y fio sysbench iperf3. Для yabs.sh требуется только curl, так как скрипт сам скачивает статические бинарные файлы для всего недостающего. Удаляйте все тестовые файлы по завершении: файл fio размером 2G, оставленный на диске объемом 20G, через несколько недель станет причиной уведомления о нехватке места.