Jak poprawnie testować wydajność VPS
Uruchom najpierw yabs.sh, potem fio, sysbench i iperf3. Sprawdź, co oznaczają wyniki CPU, pamięci, dysku i sieci oraz dlaczego jeden test nie wystarcza.
Co oznacza testowanie wydajności VPS
Aby przetestować wydajność VPS, należy zmierzyć cztery parametry: szybkość działania pojedynczego rdzenia CPU, przepustowość pamięci maszyny, liczbę małych losowych operacji dyskowych wykonywanych przez pamięć masową w ciągu sekundy oraz przepustowość zapewnianą przez łącze sieciowe. Jedno uruchomienie yabs.sh zapewnia wszystkie cztery wyniki w około dziesięć minut. Trudniejsza jest interpretacja wyników, ponieważ VPS (wirtualny serwer prywatny) współdzieli fizyczny sprzęt z innymi użytkownikami, dlatego ta sama maszyna może zwrócić jedną wartość o 03:00, a zupełnie inną o 20:00.
Najpierw należy uruchomić yabs.sh, aby szybko uzyskać ogólny obraz, a następnie ręcznie uruchomić używane przez niego narzędzia. Samodzielne uruchamianie tych narzędzi pozwala zmienić jedną flagę, obserwować zmianę wyniku i ustalić, co dokładnie mierzy dana wartość. Należy wykonać te czynności po skonfigurowaniu maszyny, a nie wcześniej. Najpierw należy wykonać kroki opisane w pierwszych dziesięciu minutach na nowym VPS, ponieważ maszyna, która nadal instaluje pierwszą partię aktualizacji, uzyskuje słabe wyniki testów z przyczyn niezwiązanych ze sprzętem.
Obejrzyj maszynę, zanim zaczniesz ją mierzyć
Połowa każdego nieudanego testu porównawczego wynika z użycia maszyny, której autor nie rozumiał.
nproc
lscpu | grep -E 'Model name|Hypervisor|Thread'
free -h
df -hT /
uname -r
systemd-detect-virtHypervisor vendor: KVM oznacza pełną wirtualizację, dlatego uruchamiane jest własne jądro. Drukowanie lxc w systemd-detect-virt lub openvz oznacza natomiast wirtualizację kontenerową: współdzielone jest jądro hosta, a limity procesora i pamięci są ustawieniami cgroup (control group), a nie wirtualnym sprzętem. W systemie z cgroup v2 limit procesora można odczytać bezpośrednio.
cat /sys/fs/cgroup/cpu.maxmax 100000 oznacza brak limitu. 200000 100000 oznacza, że można używać procesora przez 200000 mikrosekund w każdym okresie 100000 mikrosekund, czyli limit odpowiada 2 rdzeniom. Plan reklamowany jako 4 vCPU, z limitem odpowiadającym 2 rdzeniom, nigdy nie uzyska wyników porównywalnych z 4 rdzeniami. Żadne narzędzie do testów porównawczych nie wyświetla wiersza wyjaśniającego przyczynę.
df -hT / ma znaczenie z innego powodu: chodzi o kolumnę Type. Jeśli zawiera overlay, oznacza to, że działasz wewnątrz kontenera, a opisany poniżej test dysku wymaga zmiany. Należy odnotować to teraz.
Monitor czas kradzieży przez cały czas
Czas kradzieży to udział czasu, w którym wirtualny procesor był gotowy do uruchomienia, ale hypervisor przydzielił rdzeń fizyczny innemu procesowi. Jest to najbardziej użyteczny pojedynczy sygnał wskazujący, że wynik zależy od sąsiednich maszyn wirtualnych, a nie od sprzętu.
vmstat 1 10Odczytaj kolumnę st po prawej stronie. Stała wartość 0 lub 1 jest normalna. Utrzymujące się wartości powyżej 5 oznaczają, że host jest w tym momencie przeciążony, dlatego każda wartość CPU zarejestrowana w tym przedziale jest zaniżona nie z winy maszyny. top pokazuje tę samą wartość co %st w wierszu CPU. Pozostaw vmstat 1 uruchomione w drugiej sesji SSH podczas wykonywania testu wydajności i zapisz wartość czasu kradzieży 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 i Geekbench, uruchamia je i wyświetla jedno podsumowanie. Jest powszechnie używany w dyskusjach o testach VPS, dlatego wynik yabs jest najszybszym sposobem porównania wyników z inną osobą.
Jednoliniowa forma zalecana w projekcie wygląda następująco.
curl -sL yabs.sh | bashTo polecenie przekazuje bezpośrednio do powłoki dowolną zawartość udostępnianą obecnie przez ten adres URL. Należy najpierw pobrać skrypt i zapoznać się z jego treścią, a dopiero potem go uruchomić.
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ć za -s -- w przypadku potokowania albo bezpośrednio za nazwą pliku podczas uruchamiania lokalnej kopii. Przydatne opcje to: -f pomija test dysku, -i pomija test sieci, -g pomija Geekbench, -r ogranicza liczbę lokalizacji iperf3 do dwóch, -j wyświetla wyniki w formacie JSON, a -w results.json zapisuje ten kod JSON do pliku.
bash yabs.sh -r -w yabs-run1.jsonPrzed pierwszym uruchomieniem należy pamiętać o dwóch kwestiach. Geekbench przesyła wynik i wyświetla publiczny adres URL w domenie browser.geekbench.com, dlatego każda osoba mająca ten odnośnik może odczytać model procesora i wyniki. -g całkowicie pomija ten test. Ponadto etap iperf3 generuje rzeczywisty ruch sieciowy do serwerów w kilku regionach, co zmniejsza miesięczny limit transferu. Przy łączu 1 Gbit/s pełny etap testu sieci może wygenerować transfer rzędu dziesiątek gigabajtów, dlatego przy niewielkim limicie należy użyć -r, a przy łączu rozliczanym według użycia — -i.
Co oznacza każda część danych wyjściowych yabs
Sekcja dysku uruchamia fio z proporcją odczytów do zapisów wynoszącą 50/50 dla czterech rozmiarów bloków: 4k, 64k, 512k i 1m. Raportuje IOPS (liczbę operacji wejścia/wyjścia na sekundę) oraz przepustowość dla każdego rozmiaru. Wiersz 4k ma znaczenie w przypadku bazy danych, serwera pocztowego lub dowolnego systemu wykonującego wiele małych zapisów, ponieważ większość operacji wejścia/wyjścia na serwerach dotyczy małych, rozproszonych bloków. Wiersz 1m ma znaczenie w przypadku kopii zapasowych i wideo, gdzie przesyłane są długie sekwencje bajtów.
Sekcja sieciowa uruchamia iperf3 względem serwerów publicznych w kilku regionach, w obu kierunkach, z użyciem równoległych strumieni. Niską wartość należy traktować jako sygnał do dalszej weryfikacji, a nie jako rozstrzygający wynik, ponieważ publiczne serwery iperf3 są współdzielone i często przeciążone. Słaby wynik może więc wynikać ze stanu systemu po stronie zdalnej.
Sekcja Geekbench zawiera wynik dla jednego rdzenia oraz wynik dla wielu rdzeni. Wynik dla jednego rdzenia wskazuje, jak szybko kończy się obsługa jednego żądania, jedna kompilacja lub jedno zapytanie. Wynik dla wielu rdzeni informuje głównie o rzeczywistej liczbie przydzielonych rdzeni.
Dysk: uruchomienie fio bezpośrednio
fio (flexible IO tester) jest narzędziem używanym w sekcji dotyczącej dysku w yabs. Bezpośrednie uruchomienie fio pozwala właściwie zinterpretować poszczególne flagi.
sudo apt update && sudo apt install -y fio sysbench iperf3Test losowego odczytu 4k przy głębokości kolejki 32, przeprowadzony w systemie plików, którego faktyczna wydajność ma znaczenie:
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, który należy odczytać z wyników, wygląda następująco.
read: IOPS=184k, BW=719MiB/s (754MB/s)(42.1GiB/60001msec)Poniżej fio wyświetla blok clat percentiles. Warto podać percentyl 99.00, ponieważ określa on czas oczekiwania najwolniejszego z każdych 100 żądań. Średnie opóźnienie ukrywa właśnie te przestoje, które są zauważalne dla użytkownika.
--direct=1otwiera plik za pomocąO_DIRECT, dzięki czemu odczyty omijają pamięć podręczną stron jądra. Bez tej opcji drugi przebieg po pliku o rozmiarze 2G na maszynie z 8G pamięci RAM jest obsługiwany z pamięci. W takiej sytuacji fio raportuje miliony IOPS. Ta wartość jest rzeczywista, ale dotyczy wydajności pamięci.--ioengine=libaioprzesyła żądania asynchronicznie. Dzięki temu--iodepth=32może utrzymywać 32 żądania w toku. W przypadku synchronicznego silnika, takiego jakpsync, wartość iodepth większa niż 1 nie daje żadnego efektu. Mierzone jest wtedy jedno żądanie naraz.--time_based --runtime=60uruchamia test na stałe 60 sekund zamiast do wykonania stałej liczby operacji. Dzięki temu szybki i wolny dysk są testowane przez taki sam czas rzeczywisty, a porównanie pozostaje miarodajne.--size=2Gustawia rozmiar pliku testowego. Należy ustawić go powyżej rozmiaru każdej pamięci podręcznej na ścieżce I/O i wcześniej sprawdzić dostępne wolne miejsce.
Losowy zapis wymaga użycia tego samego polecenia z --rw=randwrite. Należy uruchomić go osobno, a następnie usunąć plik.
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ć obciążenie bardziej zbliżone do rzeczywistego ruchu, należy użyć --rw=randrw --rwmixread=70. Klasa używanej pamięci masowej wpływa na te wyniki bardziej niż dowolna flaga. Różnice między tymi klasami opisano w porównaniu pamięci masowej NVMe i SATA SSD na VPS.
Gdy fio kończy działanie z błędem Unknown error -1
Bezpośredni dostęp do operacji wejścia-wyjścia nie jest dostępny w każdym systemie plików. overlay, czyli system plików domyślnie udostępniany kontenerowi przez Docker, oraz kilka sieciowych systemów plików nie obsługuje O_DIRECT. W takiej sytuacji libaio przekazuje żądanie, którego jądro nie może zrealizować, a fio przerywa działanie:
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 zawiera overlay, wskaż w --filename ścieżkę na rzeczywistym magazynie danych, na przykład w woluminie montowanym za pomocą bind mount, albo uruchom fio na hoście zamiast w kontenerze. Jeśli dostęp do rzeczywistego magazynu danych jest niemożliwy, buforowane uruchomienie synchroniczne przynajmniej potwierdzi poprawność samego polecenia.
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 jasno określić, co mierzy takie uruchomienie. Po pierwszym przebiegu plik 256M znajduje się w pamięci podręcznej stron, dlatego wartość IOPS opisuje pamięć RAM. Użyj tego przebiegu, aby potwierdzić instalację fio i poprawne przetworzenie flag. Nie przedstawiaj tego wyniku jako wyniku dla dysku.
Dlaczego dd nie jest narzędziem do testowania wydajności dysku
dd pojawia się w wielu wątkach dotyczących VPS i odpowiada na jedno wąskie pytanie.
dd if=/dev/zero of=./ddtest bs=1M count=1024 oflag=direct conv=fdatasync
rm -f ./ddtestMierzy to przepustowość sekwencyjnego zapisu przy użyciu jednego wątku i jednego żądania przetwarzanego w danym momencie. Jest to rozsądny test kontrolny. Nie mówi nic o losowych operacjach wejścia-wyjścia ani o tym, co się dzieje, gdy jednocześnie pojawią się 32 żądania. Po usunięciu oflag=direct pomiar dotyczy głównie szybkości, z jaką jądro systemu przyjmuje zapisy do pamięci. Z tego powodu wartości dd cytowane w postach na forach często są absurdalne.
CPU: sysbench cpu
sysbench cpu --cpu-max-prime=20000 --threads=1 run
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) runNależy zachować wynik events per second. Najpierw należy uruchomić test jednowątkowy. Jest to wartość określająca, jak szybko kończy się jedno żądanie PHP lub jedno zadanie kompilacji. Wynik ten najbardziej różni się między hostami w tej samej cenie. Następnie należy uruchomić test ze wszystkimi wątkami. Pokazuje on, czy vCPU są oddzielnymi rdzeniami, czy tylko częściami jednego rdzenia.
Należy jasno określić zakres pomiaru. sysbench cpu wielokrotnie wyszukuje liczby pierwsze za pomocą 64-bitowej arytmetyki całkowitoliczbowej. Nie obciąża przepustowości pamięci, jednostek wektorowych ani pamięci podręcznej w sposób przypominający rzeczywiste obciążenie. Dlatego nadaje się do porównywania dwóch hostów, ale słabo przewiduje działanie aplikacji.
Ubuntu 24.04 zawiera sysbench 1.0.20, w którym nazwa testu jest podawana jako pierwsza. Skopiowanie polecenia zawierającego --test=cpu ze starszego wpisu powoduje wyświetlenie WARNING: the --test option is deprecated. Wyników sysbench 0.4 i sysbench 1.0 nie można ze sobą porównywać. Nie należy więc porównywać własnego wyniku z opublikowaną wartością, przy której nie podano wersji.
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 jest podawany w MiB/sec, a odczyt jest szybszy niż zapis na każdej maszynie. Wartość --memory-block-size należy ustawić na 1M i zachować identyczną na każdym porównywanym hoście. Przy 1K wynik gwałtownie spada, ponieważ narzut każdej operacji występuje tysiąc razy częściej. W efekcie mierzony jest koszt pętli zamiast przepustowości pamięci. Jest to najczęściej niezgodna flaga w publikowanych wynikach testów pamięci.
Sieć: iperf3
Rzetelny test przepustowości należy przeprowadzić względem drugiej kontrolowanej maszyny. Dzięki temu wiadomo, co dzieje się po obu stronach.
Na drugim końcu:
iperf3 -sPolecenie nasłuchuje na porcie TCP 5201. Port należy otworzyć tylko dla adresu, z którego wykonywany jest test, a po jego zakończeniu zamknąć. Składnię opisano w Podstawowe reguły zapory ufw na VPS.
Z testowanego 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 8Pierwszy test mierzy wysyłanie danych z testowanej maszyny. -R odwraca kierunek, więc mierzy pobieranie danych. -P 8 otwiera osiem równoległych strumieni.
Należy uruchomić zarówno pojedynczy strumień, jak i wersję równoległą, ponieważ odpowiadają one na różne pytania. Jedno połączenie TCP może utrzymywać tylko tyle niepotwierdzonych danych, na ile pozwala jego okno, dlatego jego maksymalna przepustowość wynosi w przybliżeniu rozmiar okna podzielony przez czas RTT. Przy opóźnieniu 80 ms i oknie 4 MB limit ten wynosi około 400 Mbit/s, niezależnie od szybkości używanego łącza. Wynik dla pojedynczego strumienia pokazuje, jaką przepustowość uzyska jedno pobieranie. Wynik dla strumieni równoległych pokazuje przepustowość łącza.
Podczas testu należy kontrolować wykorzystanie dostępnego limitu transferu. Trzydzieści sekund przy szybkości 1 Gbit/s oznacza przesłanie około 3.75 GB. Test zostanie uruchomiony kilka razy w każdym kierunku.
Wartości referencyjne i sposób interpretacji własnych wyników
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 wolumin NVMe w publikowanych wynikach zwykle osiąga około 180,000 operacji I/O na sekundę (IOPS) dla losowego odczytu 4k. Lokalny dysk SSD SATA osiąga około 90,000. Sieciowa pamięć blokowa, w przypadku której każde żądanie przechodzi przez sieć, zanim dotrze do dysku, osiąga wartości bliższe 12,000, natomiast dysk talerzowy uzyskuje około 180, ponieważ przy każdym losowym żądaniu musi przemieścić głowicę.
Są to typowe publikowane wartości dla poszczególnych klas pamięci masowej, a nie pomiary wykonane na jednym hoście. Należy używać ich wyłącznie do sprawdzenia, czy własny wynik mieści się w odpowiednim rzędzie wielkości. Jeśli plan oferowany jako NVMe osiąga w teście kilka tysięcy IOPS dla losowego odczytu 4k, należy najpierw sprawdzić, czy --direct=1 było włączone. Jeśli tak, pamięć masowa nie odpowiada opisowi produktu albo jest współdzielona z bardzo obciążonym sąsiednim użytkownikiem.
Dlaczego jeden przebieg nie jest testem porównawczym
Pojedynczy wynik jest migawką jednej minuty 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 co najmniej w dwa różne dni. Należy zachować medianę i rozrzut wyników. Wynik opublikowany bez rozrzutu jest wartością marketingową.
- Przy każdym przebiegu należy zapisać czas steal. Należy odrzucić przebiegi, podczas których
stbył wysoki, albo przynajmniej odnotować ten fakt. - Test dysku należy wykonać z dwoma czasami trwania. Wiele planów zapewnia limit burst IOPS, który z czasem się odnawia, dlatego 60-sekundowy przebieg fio mierzy burst, natomiast
--runtime=600mierzy wartość minimalną. Wartość minimalna odpowiada wynikom uzyskiwanym w niekorzystnych warunkach. - Należy sprawdzić, czy nie działa nic innego. Uruchomienie przez
unattended-upgradestransakcji apt w trakcie testu CPU powoduje rzeczywisty spadek wyniku, a wykonanieps -e -o comm= | grep -E 'apt|dpkg'przed każdym przebiegiem zajmuje sekundę. - Należy zmieniać jedną zmienną naraz. Różne wersje narzędzi, rozmiary bloków lub liczby wątków dają wyniki, których nie można porównywać, niezależnie od ich pozornego podobieństwa.
Porównując dwóch dostawców, należy uruchomić testy o tej samej godzinie tego samego dnia. W przeciwnym razie zostanie zmierzona pora dnia.
Ostatni zmierz własne obciążenie
Narzędzia syntetyczne porównują wydajność maszyn. Tylko własne obciążenie pokazuje, czy maszyna jest wystarczająca. Zmierz czas wykonywania czynności, którą rzeczywiście wykonujesz.
time tar -czf /tmp/bench.tgz /usr/share
rm -f /tmp/bench.tgzTo polecenie kompresuje kilkaset megabajtów, dlatego obciąża jednocześnie procesor i dysk, a wynik zmienia się wraz ze zmianą któregokolwiek z nich. Ostrzeżenie Removing leading / from member names jest normalne. Jeszcze lepiej zmierzyć czas własnej kompilacji, wykonania własnego najwolniejszego zapytania albo renderowania własnej strony. Jeśli kompilacja trwa 4 minuty na jednym hoście i 7 na innym, rozstrzyga to kwestię niezależnie od wyniku Geekbench. Jest to również pomiar pokazujący, kiedy większa maszyna przestaje być warta dodatkowych kosztów. Warto to wiedzieć przed przeczytaniem informacji o tym, ile faktycznie kosztuje VPS miesięcznie, lub przed przeniesieniem obciążenia na serwer dedykowany.
FAQ
Dlaczego za każdym razem uzyskuję inny wynik testu?
VPS współdzieli fizyczny procesor, pamięć masową i sieć z innymi dzierżawcami, dlatego wynik zależy od ich aktywności w danym momencie. Uruchom vmstat 1 podczas testu i odczytaj kolumnę st: utrzymujący się czas steal powyżej 5 oznacza duże obciążenie hosta, a wynik CPU jest niski z przyczyn niezależnych od maszyny. Rozwiązaniem jest właściwa metodyka, a nie dostrajanie. Każdy test należy uruchomić co najmniej pięć razy w różnych godzinach, a następnie podać medianę wraz z rozrzutem.
Dlaczego fio zgłasza miliony IOPS?
Niemal zawsze przyczyną jest brak --direct=1. Bez tego parametru fio odczytuje dane za pośrednictwem pamięci podręcznej stron jądra, więc po pierwszym przebiegu plik testowy 2G jest obsługiwany z pamięci RAM, a mierzona jest przepustowość pamięci. Należy dodać --direct=1 i zachować plik testowy większy niż każda pamięć podręczna na ścieżce. Jeśli --direct=1 zakończy się błędem err=-1/file:ioengines.c:321, func=get_events, error=Unknown error -1, należy uruchomić df -hT .: Type overlay nie obsługuje O_DIRECT, dlatego test należy skierować do rzeczywistej pamięci masowej.
Czy yabs.sh wystarcza samodzielnie?
Do wstępnej oceny tak. Uruchamia fio dla czterech rozmiarów bloków, iperf3 w obu kierunkach oraz Geekbench i wyświetla jedno podsumowanie, które mogą odczytać inni użytkownicy. Przestaje wystarczać, gdy trzeba ustalić przyczynę konkretnego wyniku, ponieważ nie można ustawiać jego flag osobno dla każdego testu. Gdy wynik yabs wygląda nieprawidłowo, należy odtworzyć test bezpośrednio za pomocą fio lub sysbench i zmieniać jedną flagę naraz.
Która pojedyncza wartość najlepiej przewiduje działanie aplikacji?
W przypadku większości obciążeń internetowych i bazodanowych najważniejsze są, w tej kolejności, szybkość pojedynczego rdzenia procesora oraz opóźnienie losowego odczytu 4k. Wartości przepustowości wyglądają imponująco, ale rzadko o czymkolwiek decydują, ponieważ typowe żądanie jest niewielkie. Należy podawać percentyl 99 z bloku fio clat percentiles zamiast średniej, ponieważ użytkownik zauważa właśnie jedno wolne żądanie na sto.
Czy przed wykonaniem testów trzeba coś zainstalować?
fio, sysbench i iperf3 są dostępne w repozytoriach Ubuntu i Debian: sudo apt install -y fio sysbench iperf3. yabs.sh wymaga tylko curl, ponieważ pobiera statyczne pliki binarne brakujących składników. Po zakończeniu należy usunąć wszystkie pliki testowe, ponieważ pozostawiony plik fio o rozmiarze 2G na dysku 20G po kilku tygodniach spowoduje alarm o braku wolnego miejsca.