Jak poprawnie wykonać benchmark VPS
Dowiedz się, jak rzetelnie przetestować wydajność VPS za pomocą skryptu yabs.sh oraz narzędzi fio, sysbench i iperf3. Poznaj powody, dla których pojedynczy pomiar jest niewiarygodny.
Na czym polega benchmarkowanie VPS
Benchmarkowanie VPS polega na pomiarze czterech parametrów: szybkości pracy pojedynczego rdzenia CPU, przepustowości pamięci operacyjnej, liczby operacji wejścia/wyjścia na sekundę (IOPS) dla małych, losowych odczytów i zapisów na dysku oraz przepustowości łącza sieciowego. Jedno uruchomienie yabs.sh pozwala uzyskać wszystkie te dane w około dziesięć minut. Interpretacja wyników jest trudniejsza, ponieważ VPS (virtual private server) współdzieli fizyczny sprzęt z innymi użytkownikami, przez co ta sama maszyna może wykazywać zupełnie inne wartości o godzinie 03:00 i 20:00.
Plan zakłada uruchomienie yabs.sh w celu uzyskania szybkiego podglądu, a następnie ręczne uruchomienie poszczególnych narzędzi. Samodzielne testowanie pozwala na zmianę flagi, obserwację zmiany wyniku i zrozumienie, co dany parametr faktycznie mierzy. Testy należy przeprowadzać po skonfigurowaniu maszyny, a nie przed. Kroki opisane w pierwsze dziesięć minut na nowym VPS muszą zostać wykonane najpierw, ponieważ serwer w trakcie pobierania pierwszej serii aktualizacji osiąga słabe wyniki z przyczyn niezwiązanych z wydajnością sprzętu.
Analiza maszyny przed wykonaniem pomiarów
Połowa błędnych wyników benchmarków wynika z braku zrozumienia specyfiki maszyny przez autora testu.
nproc
lscpu | grep -E 'Model name|Hypervisor|Thread'
free -h
df -hT /
uname -r
systemd-detect-virtHypervisor vendor: KVM oznacza pełną wirtualizację, co wiąże się z uruchomieniem własnego jądra systemu. Wyświetlenie lxc lub openvz za pomocą systemd-detect-virt oznacza wirtualizację kontenerową: współdzielone jest jądro systemu gospodarza, a limity CPU i pamięci są ustawieniami cgroup (control group), a nie wirtualnym sprzętem. W systemach z cgroup v2 limit CPU można odczytać bezpośrednio.
cat /sys/fs/cgroup/cpu.maxmax 100000 oznacza brak limitu (quota). 200000 100000 oznacza możliwość wykorzystania 200000 mikrosekund czasu CPU w każdym okresie 100000 mikrosekund, co odpowiada limitowi dwóch rdzeni. Plan reklamowany jako 4 vCPU z limitem dwóch rdzeni nigdy nie osiągnie wyników czterech rdzeni, a żadne narzędzie benchmarkowe nie wyświetli komunikatu wyjaśniającego przyczynę.
df -hT / ma znaczenie z innego powodu: kolumna Type. Jeśli widnieje w niej overlay, oznacza to pracę wewnątrz kontenera, co wymaga zmiany sposobu testowania dysku. Należy to odnotować.
Monitorowanie steal time w czasie rzeczywistym
Steal time to udział czasu, w którym wirtualny procesor był gotowy do pracy, ale hypervisor przydzielił fizyczny rdzeń innemu użytkownikowi. Jest to najważniejszy pojedynczy sygnał wskazujący, że wynik zależy od sąsiednich maszyn, a nie od wydajności sprzętu.
vmstat 1 10Należy obserwować kolumnę st po prawej stronie. Stałe wartości 0 lub 1 są normalne. Utrzymujące się wartości powyżej 5 oznaczają, że host jest w danej chwili przeciążony, więc każda liczba dotycząca procesora zarejestrowana w tym oknie jest zaniżona z przyczyn niezależnych od maszyny. Wartość top pokazuje ten sam odczyt co %st w wierszu CPU. Podczas wykonywania benchmarków należy uruchomić vmstat 1 w drugiej sesji SSH i zapisywać wartość steal obok każdego wyniku.
Rozpoczęcie pracy z yabs.sh
yabs.sh (Yet Another Bench Script) to skrypt powłoki, który pobiera statyczne pliki binarne fio, iperf3 oraz Geekbench, uruchamia je i generuje zbiorcze podsumowanie. Jest to standardowe narzędzie w dyskusjach na temat wydajności VPS, dlatego wynik yabs stanowi najszybszy sposób na porównanie parametrów serwera.
Oficjalna metoda uruchomienia skryptu za pomocą jednej linii poleceń wygląda następująco.
curl -sL yabs.sh | bashPolecenie to przesyła zawartość pobraną z adresu URL bezpośrednio do powłoki. Należy pobrać skrypt, zapoznać się z jego treścią, a następnie uruchomić go lokalnie.
curl -sLo yabs.sh https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh
less yabs.sh
bash yabs.shFlagi należy umieszczać po -s -- w przypadku potokowania lub bezpośrednio po nazwie pliku w przypadku uruchamiania kopii lokalnej. Przydatne opcje to: -f pomija test dysku, -i pomija test sieci, -g pomija test Geekbench, -r ogranicza liczbę lokalizacji iperf3 do dwóch, -j wyświetla wyniki w formacie JSON, a -w results.json zapisuje ten format JSON do pliku.
bash yabs.sh -r -w yabs-run1.jsonPrzed pierwszym uruchomieniem należy zwrócić uwagę na dwie kwestie. Geekbench przesyła wynik do sieci i generuje publiczny adres URL w serwisie browser.geekbench.com, co oznacza, że każda osoba posiadająca ten link może odczytać model procesora oraz uzyskane wyniki. -g pozwala całkowicie pominąć ten test. Po drugie, etap iperf3 generuje rzeczywisty ruch sieciowy do serwerów w różnych regionach, co jest wliczane do miesięcznego limitu transferu danych. Na łączu 1 Gbit/s pełny test sieci może wygenerować transfer rzędu kilkudziesięciu gigabajtów, dlatego przy małych limitach należy stosować -r, a w przypadku łączy rozliczanych za ilość danych – -i.
Znaczenie poszczególnych sekcji wyniku yabs
Sekcja disk uruchamia fio z mieszanym odczytem i zapisem w proporcji 50/50 dla czterech rozmiarów bloku: 4k, 64k, 512k oraz 1m. Raportuje ona IOPS (operacje wejścia/wyjścia na sekundę) oraz przepustowość dla każdego z nich. Wiersz 4k jest kluczowy w przypadku baz danych, serwerów pocztowych oraz wszelkich zastosowań wymagających wielu małych operacji zapisu, ponieważ większość operacji wejścia/wyjścia na serwerze jest niewielka i rozproszona. Wiersz 1m dotyczy kopii zapasowych oraz plików wideo, gdzie przesyłane są długie ciągi bajtów.
Sekcja network uruchamia iperf3 w kierunku publicznych serwerów w różnych regionach, w obu kierunkach, przy użyciu równoległych strumieni. Niską wartość w tym teście należy traktować jako sygnał do dalszej weryfikacji, a nie jako ostateczny wynik, ponieważ publiczne serwery iperf3 są współdzielone i często przeciążone, więc słaby wynik może wynikać z ograniczeń po stronie zdalnej.
Sekcja Geekbench podaje wynik dla pojedynczego rdzenia (single core) oraz dla wielu rdzeni (multi core). Wynik single core określa szybkość wykonania pojedynczego żądania, kompilacji lub zapytania. Wynik multi core informuje głównie o rzeczywistej liczbie dostępnych rdzeni.
Dysk: samodzielne uruchomienie fio
fio (flexible IO tester) to narzędzie wykorzystywane w sekcji dyskowej yabs. Bezpośrednie korzystanie z niego pozwala na pełne wykorzystanie dostępnych flag.
sudo apt update && sudo apt install -y fio sysbench iperf3Test losowego odczytu 4k przy głębokości kolejki 32, wykonany na wybranym systemie plików:
fio --name=randread4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randread --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reportingWiersz podsumowania w wynikach wygląda następująco.
read: IOPS=184k, BW=719MiB/s (754MB/s)(42.1GiB/60001msec)Poniżej fio drukuje blok clat percentiles. Wartość 99.00th percentile jest najbardziej istotna, ponieważ określa czas oczekiwania najwolniejszego z każdych stu żądań. Średnie opóźnienie maskuje zatory, które są odczuwalne dla użytkownika.
--direct=1otwiera plik z flagąO_DIRECT, dzięki czemu odczyty omijają pamięć podręczną stron jądra systemu. Bez tego drugie przejście przez plik 2G na maszynie z 8G pamięci RAM jest obsługiwane z pamięci, a fio raportuje miliony operacji IOPS. Wynik ten jest poprawny technicznie, ale dotyczy wydajności pamięci RAM, a nie dysku.--ioengine=libaioprzesyła żądania asynchronicznie, co pozwala--iodepth=32na utrzymanie 32 żądań w toku. W przypadku silnika synchronicznego, takiego jakpsync, wartość iodepth powyżej 1 nie przynosi efektu, więc mierzona jest tylko jedna operacja na raz.--time_based --runtime=60uruchamia test na sztywno przez 60 sekund zamiast wykonywać określoną ilość pracy. Dzięki temu szybki i wolny dysk są testowane przez ten sam czas, co zapewnia sprawiedliwe porównanie.--size=2Gokreśla rozmiar pliku testowego. Należy ustawić go na wartość większą niż jakakolwiek pamięć podręczna na ścieżce zapisu i upewnić się, że na dysku jest wystarczająca ilość wolnego miejsca.
Test losowego zapisu wykonuje się tym samym poleceniem z flagą --rw=randwrite. Należy uruchomić go oddzielnie, a następnie usunąć plik testowy.
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-testfileAby uzyskać mieszane obciążenie zbliżone do rzeczywistego ruchu, należy użyć --rw=randrw --rwmixread=70. Klasa nośnika danych wpływa na wyniki znacznie bardziej niż jakakolwiek flaga, a podział ten został omówiony w różnice między pamięcią NVMe a SATA SSD na VPS.
Gdy fio kończy działanie z błędem Unknown error -1
Bezpośrednie wejście/wyjście (Direct IO) nie jest dostępne w każdym systemie plików. overlay, domyślny system plików przydzielany kontenerom przez Docker, oraz wiele sieciowych systemów plików nie obsługuje O_DIRECT, dlatego libaio wysyła żądanie, którego jądro nie może obsłużyć, a fio przerywa pracę:
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 -1Najpierw uruchom df -hT .. Jeśli kolumna Type wskazuje overlay, skieruj --filename na ścieżkę w rzeczywistej pamięci masowej, taką jak wolumen typu bind mount, lub uruchom fio na hoście zamiast w kontenerze. Jeśli dostęp do rzeczywistej pamięci masowej jest niemożliwy, buforowane uruchomienie synchroniczne pozwoli przynajmniej potwierdzić poprawność samej komendy.
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-testfileNależy rzetelnie określać charakter takiego testu. Po pierwszym przebiegu plik o rozmiarze 256M znajduje się w pamięci podręcznej stron (page cache), więc wynik IOPS opisuje wydajność pamięci RAM. Użyj tego testu wyłącznie do potwierdzenia, że fio jest zainstalowane, a flagi są poprawnie interpretowane. Nigdy nie przedstawiaj takiego wyniku jako wydajności dysku.
Dlaczego dd nie jest narzędziem do testowania wydajności dysków
dd pojawia się w wielu wątkach dotyczących VPS i odpowiada na jedno, bardzo wąskie pytanie.
dd if=/dev/zero of=./ddtest bs=1M count=1024 oflag=direct conv=fdatasync
rm -f ./ddtestTo polecenie mierzy przepustowość zapisu sekwencyjnego przy użyciu jednego wątku i jednego żądania w kolejce. Jest to akceptowalny test poprawności działania. Nie mówi on jednak nic o operacjach wejścia/wyjścia losowego (random IO) ani o zachowaniu systemu, gdy jednocześnie napływają 32 żądania. Pominięcie oflag=direct sprawia, że wynik odzwierciedla głównie szybkość, z jaką jądro systemu przyjmuje dane do pamięci operacyjnej. Dlatego wartości dd podawane na forach są często absurdalne.
CPU: sysbench cpu
sysbench cpu --cpu-max-prime=20000 --threads=1 run
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) runWartością, którą należy zachować, jest events per second. Test należy uruchomić najpierw w trybie jednowątkowym. Jest to liczba decydująca o tym, jak szybko kończy się pojedyncze żądanie PHP lub zadanie kompilacji, i to ona najbardziej różni się między hostami w tej samej cenie. Następnie należy uruchomić test z wykorzystaniem wszystkich wątków, co pokaże, czy vCPU są oddzielnymi rdzeniami, czy wycinkami jednego rdzenia.
Należy jasno określić, co mierzy ten test: sysbench cpu wielokrotnie znajduje liczby pierwsze przy użyciu 64-bitowej arytmetyki całkowitoliczbowej. Nie obciąża on przepustowości pamięci, jednostek wektorowych ani pamięci podręcznej w sposób przypominający rzeczywiste obciążenie, dlatego jest przydatny do porównywania dwóch hostów, ale nie nadaje się do przewidywania wydajności konkretnej aplikacji.
Ubuntu 24.04 dostarcza sysbench 1.0.20, w którym nazwa testu występuje na początku. Skopiowanie polecenia z --test=cpu ze starego wpisu spowoduje błąd WARNING: the --test option is deprecated. Wyniki z sysbench 0.4 oraz sysbench 1.0 nie są w żaden sposób porównywalne, dlatego nigdy nie należy odnosić własnych pomiarów do opublikowanych wyników, które nie określają wersji narzędzia.
Pamięć: 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 runWynik podawany jest w MiB/s, a odczyt na każdej maszynie przebiega szybciej niż zapis. Parametr --memory-block-size należy utrzymywać na poziomie 1M i zachowywać jego stałą wartość dla wszystkich porównywanych hostów. Przy 1K wynik drastycznie spada, ponieważ narzut na operację jest naliczany tysiąckrotnie częściej, co sprawia, że mierzony jest koszt pętli, a nie przepustowość pamięci. Jest to najczęściej błędnie dobierana flaga w publikowanych wynikach testów pamięci.
Sieć: iperf3
Rzetelnym sposobem na przetestowanie przepustowości jest użycie drugiej maszyny, którą się zarządza, ponieważ wtedy znany jest stan obu końców połączenia.
Na zdalnym końcu:
iperf3 -sPolecenie to nasłuchuje na porcie TCP 5201. Port należy otworzyć wyłącznie dla adresu, z którego wykonywany jest test, a po zakończeniu pracy zamknąć. Podstawowe reguły zapory ufw na VPS opisuje składnię.
Z testowanego serwera 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 8Pierwsze polecenie mierzy prędkość wysyłania z testowanej maszyny. Flaga -R odwraca kierunek, co pozwala zmierzyć prędkość pobierania. Flaga -P 8 otwiera osiem równoległych strumieni.
Należy uruchomić zarówno test pojedynczego strumienia, jak i wersję równoległą, ponieważ odpowiadają one na różne pytania. Jedno połączenie TCP może obsłużyć tylko tyle niepotwierdzonych danych, na ile pozwala jego okno, więc jego limit wynosi w przybliżeniu rozmiar okna podzielony przez czas podróży w obie strony (RTT). Przy opóźnieniu 80 ms i oknie 4 MB limit ten wynosi około 400 Mbit/s, niezależnie od rzeczywistej szybkości łącza. Wynik dla pojedynczego strumienia informuje o prędkości pojedynczego pobierania. Wynik równoległy wskazuje na całkowitą przepustowość łącza.
Podczas testów należy monitorować limit transferu danych. Trzydzieści sekund przy 1 Gbit/s przesyła około 3,75 GB, a testy będą wykonywane wielokrotnie w każdym kierunku.
Wartości referencyjne i sposób ich interpretacji
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"
}
]Lokalny wolumen NVMe w opublikowanych wynikach osiąga zazwyczaj około 180,000 operacji IOPS przy losowym odczycie 4k. Lokalny dysk SATA SSD uzyskuje wynik w okolicach 90,000. Sieciowa pamięć masowa typu block storage, w której każde żądanie przesyłane jest przez sieć przed dotarciem do dysku, osiąga wartości bliższe 12,000, natomiast dysk talerzowy zarządza około 180, co wynika z konieczności fizycznego przemieszczania głowicy przy każdym losowym żądaniu.
Są to typowe, publikowane wartości dla każdej klasy pamięci masowej, a nie pomiary z jednego konkretnego hosta. Należy je wykorzystywać wyłącznie w jednym celu: weryfikacji, czy uzyskany wynik mieści się w odpowiednim rzędzie wielkości. Jeśli plan sprzedawany jako NVMe osiąga w testach wydajności zaledwie kilka tysięcy operacji IOPS 4k, należy najpierw sprawdzić, czy opcja --direct=1 była włączona. Jeśli tak, oznacza to, że albo pamięć masowa nie odpowiada opisowi na stronie produktu, albo zasoby są współdzielone z bardzo obciążonym sąsiadem.
Dlaczego pojedynczy przebieg nie jest benchmarkiem
Pojedynczy wynik to migawka z jednej minuty pracy na współdzielonej maszynie. Należy traktować go jako jedną próbkę.
- Każdy test należy uruchomić co najmniej pięć razy, w różnych godzinach i w ciągu co najmniej dwóch różnych dni. Należy zachować medianę oraz rozrzut wyników. Wynik opublikowany bez podania rozrzutu jest jedynie liczbą marketingową.
- Obok każdego przebiegu należy rejestrować czas steal time. Należy odrzucić przebiegi, w których wartość
stbyła wysoka, lub przynajmniej odnotować ten fakt. - Test dysku należy wykonać w dwóch wariantach czasowych. Wiele planów oferuje limit burst IOPS, który odnawia się z czasem, więc 60-sekundowy test fio mierzy wydajność chwilową, podczas gdy
--runtime=600mierzy wydajność bazową. Wydajność bazowa to parametr, na który można liczyć w niekorzystnych warunkach. - Należy upewnić się, że w tle nie działają inne procesy. Uruchomienie transakcji
unattended-upgradesw trakcie testu CPU powoduje realne straty wydajności, a wykonanieps -e -o comm= | grep -E 'apt|dpkg'przed każdym przebiegiem zajmuje sekundę. - Należy zmieniać tylko jedną zmienną na raz. Różne wersje narzędzi, rozmiary bloków czy liczba wątków generują wyniki, których nie można porównywać, niezależnie od tego, jak bardzo są do siebie zbliżone.
Podczas porównywania dwóch dostawców testy należy przeprowadzać o tej samej godzinie i tego samego dnia. W przeciwnym razie mierzonym parametrem jest pora dnia.
Na końcu przetestuj własne obciążenie
Narzędzia syntetyczne szeregują maszyny. Tylko własne obciążenie pozwala ocenić, czy maszyna jest wystarczająca. Zmierz czas operacji, które faktycznie wykonujesz.
time tar -czf /tmp/bench.tgz /usr/share
rm -f /tmp/bench.tgzTo polecenie kompresuje kilkaset megabajtów, więc obciąża jednocześnie procesor oraz dysk i reaguje na zmiany w wydajności któregokolwiek z nich. Ostrzeżenie Removing leading / from member names jest normalne. Jeszcze lepiej zmierzyć czas własnej kompilacji, najwolniejszego zapytania lub renderowania strony. Jeśli kompilacja trwa 4 minuty na jednym hoście i 7 na drugim, kwestia wydajności jest rozstrzygnięta, niezależnie od wyników Geekbench. Jest to również pomiar, który wskazuje moment, w którym dalsze zwiększanie zasobów przestaje być opłacalne. Warto o tym wiedzieć przed sprawdzeniem ile faktycznie kosztuje VPS miesięcznie lub przeniesieniem obciążenia na serwer dedykowany.
FAQ
Dlaczego za każdym razem otrzymuję inny wynik benchmarku?
VPS współdzieli fizyczny procesor, pamięć masową i sieć z innymi użytkownikami, więc wynik zależy od ich aktualnej aktywności. Uruchom vmstat 1 podczas testu i sprawdź kolumnę st: stały czas steal time powyżej 5 oznacza, że host był obciążony, a wynik CPU jest niski z przyczyn niezależnych od Twojej maszyny. Rozwiązaniem jest odpowiednia metodologia, a nie optymalizacja. Wykonaj każdy test co najmniej pięć razy o różnych porach, a następnie podaj medianę wraz z rozrzutem wyników.
Dlaczego fio raportuje miliony IOPS?
Prawie zawsze dlatego, że brakuje parametru --direct=1. Bez niego fio odczytuje dane z pamięci podręcznej strony jądra (kernel page cache), więc po pierwszym przebiegu plik testowy o rozmiarze 2G jest serwowany z pamięci RAM, co oznacza pomiar przepustowości pamięci. Dodaj --direct=1 i zadbaj, aby plik testowy był większy niż jakakolwiek pamięć podręczna na ścieżce dostępu. Jeśli --direct=1 zakończy się błędem err=-1/file:ioengines.c:321, func=get_events, error=Unknown error -1, uruchom df -hT .: Type typu overlay nie obsługuje O_DIRECT, więc skieruj test na rzeczywisty nośnik danych.
Czy yabs.sh wystarczy do pełnej oceny?
Do wstępnej oceny – tak. Narzędzie uruchamia fio dla czterech rozmiarów bloku, iperf3 w obu kierunkach oraz Geekbench, generując podsumowanie zrozumiałe dla innych. Przestaje wystarczać, gdy chcesz zrozumieć przyczynę konkretnego wyniku, ponieważ nie pozwala na zmianę flag dla poszczególnych testów. Gdy wynik yabs wydaje się błędny, odtwórz go bezpośrednio za pomocą fio lub sysbench, zmieniając parametry pojedynczo.
Która pojedyncza wartość najlepiej przewiduje wydajność aplikacji?
Dla większości obciążeń webowych i bazodanowych jest to szybkość pojedynczego rdzenia CPU oraz opóźnienie odczytu losowego 4k. Wartości przepustowości wyglądają imponująco, ale rzadko o czymkolwiek decydują, ponieważ typowe zapytanie jest niewielkie. Zamiast średniej, sprawdzaj 99. percentyl z bloku clat percentiles w fio, ponieważ to właśnie ten jeden wolny odczyt na sto jest zauważalny dla użytkownika.
Czy muszę coś zainstalować przed wykonaniem benchmarku?
fio, sysbench oraz iperf3 znajdują się w repozytoriach Ubuntu i Debian: sudo apt install -y fio sysbench iperf3. yabs.sh wymaga jedynie curl, ponieważ automatycznie pobiera statyczne pliki binarne dla brakujących zależności. Po zakończeniu testów usuń wszystkie pliki testowe; plik fio o rozmiarze 2G pozostawiony na dysku 20G może po kilku tygodniach wywołać alert o braku miejsca na dysku.