Come fare un benchmark corretto di un VPS
Esegui prima yabs.sh, poi fio, sysbench e iperf3. Scopri cosa misurano i valori e perché una sola esecuzione non descrive le prestazioni reali del VPS.
Cosa significa eseguire un benchmark su un VPS
Per eseguire il benchmark di un VPS si misurano quattro aspetti: la velocità di esecuzione di un singolo core della CPU, la larghezza di banda della memoria, il numero di operazioni di I/O casuali di piccole dimensioni che lo storage completa ogni secondo e il throughput della connessione di rete. Una singola esecuzione di yabs.sh fornisce i risultati relativi a CPU, disco e rete in circa dieci minuti; per la larghezza di banda della memoria, usa il test separato riportato di seguito. La parte più difficile è interpretare il risultato, perché un VPS (virtual private server) condivide l'hardware fisico con altri tenant. Per questo, la stessa macchina può riportare un valore alle 03:00 e un valore molto diverso alle 20:00.
Il piano consiste nell'eseguire yabs.sh per ottenere una panoramica rapida, quindi nell'eseguire manualmente gli strumenti che lo compongono. Eseguirli direttamente permette di modificare un flag, osservare come cambia il valore e capire che cosa misura realmente. Esegui questa procedura dopo aver configurato la macchina, non prima. I passaggi descritti in i primi dieci minuti su un nuovo VPS vengono prima, perché un server che sta ancora applicando il primo ciclo di aggiornamenti produce risultati di benchmark scadenti per motivi che non dipendono dall'hardware.
Esamina la macchina prima di misurarla
Metà di ogni benchmark non attendibile dipende dal fatto che chi lo esegue non ha compreso la macchina.
nproc
lscpu | grep -E 'Model name|Hypervisor|Thread'
free -h
df -hT /
uname -r
systemd-detect-virtHypervisor vendor: KVM indica la virtualizzazione completa: viene eseguito un kernel proprio. La presenza di systemd-detect-virt, lxc o openvz indica invece la virtualizzazione tramite container: il kernel dell’host è condiviso e i limiti di CPU e memoria sono impostazioni dei cgroup (control group), non hardware virtuale. In un sistema con cgroup v2 è possibile leggere il limite della CPU dal cgroup del container; il percorso seguente vale quando quel cgroup è montato in /sys/fs/cgroup.
cat /sys/fs/cgroup/cpu.maxmax 100000 indica che questo cgroup non ha una quota propria; i cgroup antenati possono comunque imporne una. 200000 100000 indica che è possibile usare 200000 microsecondi di CPU in ogni periodo di 100000 microsecondi, cioè una quota equivalente a due core. Un piano pubblicizzato come 4 vCPU con una quota di due core non otterrà mai risultati paragonabili a quelli di quattro core. Gli strumenti di benchmark possono identificare questa limitazione: VoxelBench indica le quote CPU e segnala una CPU condivisa o soggetta a throttling quando l’host espone un numero di CPU molto superiore a quello utilizzabile dal server.
df -hT / è importante per un altro motivo: la colonna Type. Se contiene overlay, si è all’interno di un container e i risultati relativi al disco descriveranno lo storage sottostante a quell’overlay. Annotalo subito.
Controlla continuamente lo steal time
Lo steal time è la quota di tempo in cui la CPU virtuale ha atteso involontariamente mentre l’hypervisor non la schedulava. È un indicatore utile del tempo CPU non disponibile, ma non consente di distinguere tra vicini rumorosi e applicazione della quota CPU da parte del provider.
vmstat 1 10Leggi la colonna st a destra. Uno steal time sostenuto indica che il tempo CPU non era disponibile per il guest, ma un valore superiore al 5% non dimostra che l’host sia sovraccarico. I provider possono esporre deliberatamente l’applicazione della quota CPU come steal time. top mostra lo stesso valore di %st nella riga della CPU. Lascia vmstat 1 in esecuzione in una seconda sessione SSH durante il benchmark e annota il valore dello steal time accanto a ogni risultato.
Iniziare con yabs.sh
yabs.sh (Yet Another Bench Script) è uno script shell che esegue fio, iperf3 e Geekbench e stampa un riepilogo unico. Usa fio e iperf3 se sono già installati e scarica i binari statici quando non lo sono. È il linguaggio comune nelle discussioni sui benchmark VPS, quindi un output di yabs è il modo più rapido per confrontare i risultati con altri utenti.
Il progetto fornisce questo comando su una sola riga.
curl -sL yabs.sh | bashQuesto comando invia direttamente a una shell qualunque contenuto venga fornito oggi dall'URL. Scaricalo, leggilo e poi eseguilo.
curl -sLo yabs.sh https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh
less yabs.sh
bash yabs.shQuando usi una pipe, inserisci i flag dopo -s --. Quando esegui una copia locale, inseriscili direttamente dopo il nome del file. Quelli più utili sono: -f salta il test del disco, -i salta il test di rete, -g salta Geekbench, -r riduce a tre le località iperf3, -j stampa i risultati in formato JSON e -w results.json scrive quel JSON in un file.
bash yabs.sh -r -w yabs-run1.jsonPrima della prima esecuzione devi sapere due cose. Geekbench carica il risultato e stampa un URL pubblico di browser.geekbench.com, quindi chiunque possieda quel link può leggere il modello della CPU e i relativi punteggi. -g salta completamente questo test. Inoltre, la fase iperf3 trasferisce traffico reale verso server situati in più regioni, consumando la quota mensile di banda disponibile. Su una connessione da 1 Gbit/s, una fase di rete completa può trasferire decine di gigabyte. Usa quindi -r con una quota ridotta e -i su una connessione a consumo.
Significato di ogni parte dell'output di yabs
La sezione del disco esegue fio con una combinazione bilanciata al 50% di letture e scritture, usando quattro dimensioni dei blocchi: 4k, 64k, 512k e 1m. Riporta gli IOPS (operazioni di input/output al secondo) e la larghezza di banda per ciascuna dimensione. La riga 4k è quella da considerare per un database, un server di posta o qualsiasi sistema che esegue molte scritture di piccole dimensioni, perché la maggior parte dell'IO dei server è costituita da operazioni piccole e distribuite. La riga 1m è invece quella utile per backup e video, che trasferiscono sequenze lunghe di byte.
La sezione di rete esegue iperf3 verso server pubblici in diverse regioni, in entrambe le direzioni e usando flussi paralleli. Considera un valore basso come un elemento da verificare, non come una conclusione, perché i server iperf3 pubblici sono condivisi e spesso saturi. Un risultato scarso può quindi dipendere dall'estremità remota.
La sezione Geekbench mostra un punteggio single core e un punteggio multi core. Il punteggio single core indica la velocità con cui termina una singola richiesta, compilazione o query. Il punteggio multi core indica soprattutto quanti core sono effettivamente disponibili.
Disco: eseguire fio direttamente
fio (flexible IO tester) è lo strumento utilizzato dalla sezione relativa ai dischi di yabs. Eseguirlo direttamente permette di interpretare correttamente le flag.
sudo apt update && sudo apt install -y fio sysbench iperf3Un test di lettura casuale 4k con profondità della coda pari a 32, sul filesystem di interesse:
fio --name=randread4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randread --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reportingLa riga di riepilogo da leggere nell'output è questa.
read: IOPS=184k, BW=719MiB/s (754MB/s)(42.1GiB/60001msec)Subito sotto, fio stampa un blocco clat percentiles. Il percentile 99.00 è il valore da riportare, perché indica per quanto tempo ha atteso la richiesta più lenta su 100. La latenza media nasconde proprio i rallentamenti percepiti dall'utente.
--direct=1apre il file conO_DIRECT, quindi le letture bypassano la page cache del kernel. Senza questa opzione, la seconda passata su un file da 2G, in una macchina con 8G di RAM, viene servita dalla memoria e fio riporta IOPS nell'ordine dei milioni. Il valore è reale, ma misura la memoria.--ioengine=libaioinvia richieste asincrone. Questo consente a--iodepth=32di mantenerne 32 in elaborazione. Con un motore sincrono comepsync, una iodepth superiore a 1 non ha alcun effetto: si misura una richiesta alla volta.--time_based --runtime=60esegue il test per 60 secondi fissi anziché per una quantità di lavoro fissa. In questo modo un disco veloce e uno lento utilizzano lo stesso tempo effettivo e il confronto resta equo.--size=2Gimposta la dimensione del file di test. Mantienila superiore a qualsiasi cache presente nel percorso e verifica prima di avere spazio libero sufficiente.
La scrittura casuale usa lo stesso comando con --rw=randwrite. Eseguila separatamente, quindi elimina il file.
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-testfilePer un carico più simile al traffico reale, usa --rw=randrw --rwmixread=70. La classe di storage utilizzata incide sui risultati più di qualsiasi flag. Questa differenza è descritta in la differenza tra storage NVMe e SSD SATA su un VPS.
Quando fio si interrompe con Unknown error -1
L’I/O diretto non è disponibile su tutti i filesystem. Per questo, quando fio non riesce a eseguire la prima richiesta con --direct=1 impostato, la prima verifica deve riguardare l’I/O diretto. Il problema può presentarsi così:
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 -1Eseguire prima df -hT .. Un Type di overlay, il filesystem che Docker assegna per impostazione predefinita a un container, non è di per sé la causa. overlayfs inoltra O_DIRECT al filesystem sottostante e lo rifiuta solo quando quel filesystem non supporta l’I/O diretto. Di conseguenza, --direct=1 --ioengine=libaio funziona su un overlay basato su ext4 o xfs. Quando il filesystem sottostante al file di test non supporta realmente l’I/O diretto, fio normalmente lo segnala durante l’apertura del file: fio: looks like your file system does not support direct=1/buffered=0. In questo caso, impostare --filename su un percorso dello storage locale reale, ad esempio un volume montato tramite bind mount, oppure eseguire fio sull’host anziché nel container. Se non è possibile accedere allo storage reale, un’esecuzione sincrona con I/O bufferizzato dimostra almeno che il comando è corretto.
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-testfileInterpretare correttamente il risultato. Dopo il primo passaggio, il file da 256M si trova nella page cache, quindi il valore degli IOPS descrive la RAM. Usarlo per verificare che fio sia installato e che le opzioni vengano analizzate correttamente. Non presentarlo mai come un risultato del disco.
Perché dd non è un benchmark del disco
dd compare in molte discussioni sui VPS e risponde a una domanda specifica.
dd if=/dev/zero of=./ddtest bs=1M count=1024 oflag=direct conv=fdatasync
rm -f ./ddtestMisura il throughput delle scritture sequenziali con un thread e una sola richiesta in corso. È un controllo di base ragionevole. Non dice nulla sull'I/O casuale né su ciò che accade quando arrivano 32 richieste contemporaneamente. Rimuovendo oflag=direct, le scritture passano attraverso la page cache, ma conv=fdatasync forza comunque la scrittura dei dati di output sullo storage prima che il comando termini. Se si rimuove anche quello, il risultato misura soprattutto la velocità con cui il kernel accetta le scritture in memoria. Per questo i valori di dd riportati nei post dei forum sono spesso assurdi.
CPU: sysbench cpu
sysbench cpu --cpu-max-prime=20000 --threads=1 run
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) runIl valore da conservare è events per second. Esegui prima il test con un singolo thread. Questo valore determina la velocità con cui termina una richiesta PHP o un processo di compilazione e varia maggiormente tra host con lo stesso prezzo. Esegui poi il test con tutti i thread disponibili. In questo modo puoi valutare come il throughput aumenta sui vCPU assegnati.
È importante chiarire che cosa misura questo test: sysbench cpu calcola ripetutamente numeri primi mediante divisione per tentativi. Per ogni candidato calcola una radice quadrata in doppia precisione, quindi verifica i divisori usando l'operatore modulo su interi a 64 bit e confronta ogni divisore con quel limite in virgola mobile. Il carico combina quindi operazioni su interi e in virgola mobile. Non sottopone la larghezza di banda della memoria, le unità vettoriali o la cache a uno stress paragonabile a quello di un carico di lavoro reale. È quindi utile per confrontare due host, ma non per prevedere il comportamento della tua applicazione.
Ubuntu 24.04 include sysbench 1.0.20, in cui il nome del test viene indicato per primo. Se copi un comando con --test=cpu da un articolo precedente, ottieni WARNING: the --test option is deprecated. I punteggi di sysbench 0.4 e sysbench 1.0 non sono assolutamente confrontabili. Non confrontare quindi i tuoi risultati con un valore pubblicato se non ne viene indicata la versione.
Memoria: 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 runIl risultato è espresso in MiB/sec. Mantieni --memory-block-size su 1M e usa esattamente lo stesso valore su ogni host che confronti. Con 1K il valore crolla, perché sostieni l'overhead per operazione mille volte più spesso e finisci per misurare il costo del ciclo invece della larghezza di banda della memoria. Questa è l'opzione con il valore più spesso non uniforme nei risultati di memoria pubblicati.
Rete: iperf3
Il modo corretto per testare il throughput consiste nel farlo verso una seconda macchina sotto il proprio controllo, perché in questo modo si sa cosa stanno facendo entrambi gli endpoint.
Sul sistema remoto:
iperf3 -sIl comando resta in ascolto sulla porta TCP 5201. Apri la porta solo per l'indirizzo da cui esegui il test e chiudila al termine. Regole di base del firewall ufw su un VPS descrive la sintassi.
Dal VPS sottoposto al test:
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 8Il primo comando misura l'upload dalla macchina sottoposta al test. -R inverte la direzione e misura il download. -P 8 apre otto stream paralleli.
Esegui sia il test con un singolo stream sia quello parallelo, perché rispondono a domande diverse. Una singola connessione TCP può mantenere solo la quantità di dati non ancora confermati consentita dalla relativa finestra. Di conseguenza, il limite è approssimativamente pari alla dimensione della finestra divisa per il round-trip time. Con una latenza di 80 ms e una finestra di 4 MB, questo limite è di circa 400 Mbit/s, indipendentemente dalla velocità del collegamento sottostante. Il valore del singolo stream indica la velocità che otterrà un singolo download. Il valore del test parallelo indica la capacità del collegamento.
Controlla il consumo previsto dal tuo piano di banda durante il test. Trenta secondi a 1 Gbit/s trasferiscono circa 3.75 GB e dovrai eseguire il test più volte in entrambe le direzioni.
Valori di riferimento e interpretazione dei risultati
I dati alla base di questo grafico
[
{
"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"
}
]Nei risultati pubblicati, un volume NVMe locale raggiunge in genere circa 180,000 IOPS in lettura casuale 4k. Un SSD SATA locale si attesta intorno a 90,000. Lo storage a blocchi collegato in rete, in cui ogni richiesta attraversa la rete prima di raggiungere un disco, si avvicina a 12,000, mentre un disco magnetico raggiunge circa 180, perché deve spostare una testina fisica per ogni richiesta casuale.
Questi sono valori pubblicati tipici per ogni classe di storage, non misurazioni eseguite su un singolo host. Usali per un solo scopo: verificare che il tuo risultato sia dello stesso ordine di grandezza. Se un piano venduto come NVMe raggiunge nei benchmark poche migliaia di IOPS 4k, verifica prima che --direct=1 fosse attivo. In tal caso, controlla i limiti IOPS e i crediti burst del piano, oltre alla contesa dello storage e all'hardware dichiarato.
Perché una singola esecuzione non è un benchmark
Un singolo risultato è un'istantanea di un minuto su una macchina condivisa. Trattalo come un solo campione.
- Esegui ogni test almeno cinque volte, distribuite in ore diverse e in almeno due giorni diversi. Conserva la mediana e la dispersione. Un risultato pubblicato senza indicare la dispersione è un dato di marketing.
- Registra lo steal time accanto a ogni esecuzione. Conserva le esecuzioni in cui
stera elevato e verifica se riflettono una contesa o il limite CPU del piano; scartarle può nascondere le prestazioni che ricevi effettivamente. - Esegui il test del disco con due durate. Molti piani offrono un'allocazione burst di IOPS che si ricostituisce nel tempo, ma né un'esecuzione di fio di 60 secondi né
--runtime=600garantiscono di aver misurato il livello minimo. I crediti AWS gp2 possono sostenere 3,000 IOPS per almeno 30 minuti partendo da un saldo completo, quindi entrambe le esecuzioni possono misurare le prestazioni burst. Verifica il modello di crediti del provider e monitora il saldo dei crediti prima di definire un risultato come prestazione sostenuta. - Verifica che non sia in esecuzione nient'altro.
unattended-upgradesavviare una transazione apt durante un test CPU riduce il punteggio effettivo, mentreps -e -o comm= | grep -E 'apt|dpkg'prima di ogni esecuzione richiede un secondo. - Modifica una sola variabile alla volta. Versioni diverse degli strumenti, dimensioni dei blocchi o numero di thread producono valori che non possono essere confrontati, per quanto possano sembrare simili.
Quando confronti due provider, esegui i test alla stessa ora dello stesso giorno. In caso contrario avrai misurato l'ora del giorno.
Esegui per ultimo il benchmark del tuo carico di lavoro
Gli strumenti sintetici classificano le macchine. Solo il tuo carico di lavoro indica se una macchina è sufficiente. Misura il tempo dell'attività che esegui realmente.
time tar -czf /tmp/bench.tgz /usr/share
rm -f /tmp/bench.tgzQuesta operazione comprime alcune centinaia di megabyte, quindi utilizza contemporaneamente CPU e disco e cambia quando cambia uno dei due. L'avviso Removing leading / from member names è normale. Meglio ancora, misura il tempo della tua build, della query più lenta che esegui o del rendering della tua pagina. Una build che richiede 4 minuti su un host e 7 sull'altro risolve la questione, indipendentemente dal risultato di Geekbench. Questa è anche la misura che indica quando una macchina più potente non vale più il costo aggiuntivo, un'informazione utile prima di leggere quanto costa realmente un VPS al mese o di spostare il carico di lavoro su un server dedicato.
FAQ
Perché ottengo un risultato diverso ogni volta che eseguo il benchmark?
Un VPS condivide CPU fisica, storage e rete con altri tenant, quindi il risultato dipende da ciò che stanno facendo in quel momento. Esegui vmstat 1 durante il test e leggi la colonna st: uno steal time sostenuto registra il tempo di CPU non disponibile, ma può riflettere sia l'applicazione da parte del provider dell'allocazione di CPU acquistata sia la contesa sull'host. Un valore superiore al 5% non ne stabilisce la causa. La soluzione è adottare un metodo, non applicare ottimizzazioni. Esegui ogni test almeno cinque volte in ore diverse, quindi riporta la mediana insieme alla dispersione.
Perché fio riporta milioni di IOPS?
Quasi sempre perché manca --direct=1. Senza questa opzione, fio legge attraverso la page cache del kernel; dopo il primo passaggio, quindi, un file di test da 2G viene servito dalla RAM e ciò che hai misurato è la larghezza di banda della memoria. Aggiungi --direct=1 e mantieni il file di test più grande di qualsiasi cache presente nel percorso. Se --direct=1 non riesce, esegui df -hT . e verifica su quale supporto si trova il file di test. Un tipo overlay non è di per sé il problema, perché overlayfs inoltra O_DIRECT allo storage sottostante. Sposta il file di test su storage locale reale solo se il filesystem sottostante rifiuta l'IO diretto.
yabs.sh è sufficiente da solo?
Per una prima valutazione, sì. Esegue fio con quattro dimensioni di blocco, iperf3 in entrambe le direzioni e Geekbench, quindi stampa un riepilogo leggibile da altre persone. Non è più sufficiente quando vuoi capire perché un valore è quello che è, perché non puoi variare i flag per ogni test. Quando un risultato di yabs appare errato, riproducilo direttamente con fio o sysbench e modifica un flag alla volta.
Quale singolo valore predice la reattività della mia applicazione?
La velocità della CPU su un singolo core e la latenza di lettura casuale 4k, in quest'ordine, per la maggior parte dei carichi di lavoro web e database. I valori di throughput sembrano impressionanti e raramente sono determinanti, perché una richiesta tipica è piccola. Riporta il percentile 99 dal blocco clat percentiles di fio invece della media, perché la richiesta lenta su cento è quella che l'utente nota.
Devo installare qualcosa prima del benchmark?
fio, sysbench e iperf3 sono tutti disponibili negli archivi Ubuntu e Debian: sudo apt install -y fio sysbench iperf3. yabs.sh viene eseguito in Bash e richiede curl o wget per i download, oltre a tar per estrarre Geekbench; senza tar, salta Geekbench. Usa fio e iperf3 quando sono installati e scarica binari statici quando non sono disponibili. Elimina ogni file di test al termine, perché un file fio da 2G lasciato su un disco da 20G può diventare, dopo alcune settimane, l'origine di un avviso di disco pieno.