VPS Benchmark Guide: Test CPU, RAM, Disk and Network (2026)

Benchmark a VPS properly: read YABS before you run it, use a fixed fio job file, sysbench and your own iperf3 server, log steal time, repeat every test and compare medians.

Title card reading “Benchmark a VPS properly” for the HourlyVPS guide to benchmarking a VPS with YABS, fio, sysbench, iperf3 and steal time

A VPS benchmark measures four things: CPU speed on one core and on all cores, disk performance (4K random IOPS with their latency, plus 1M sequential throughput), network throughput to a far end you know, and steal time, the CPU time the hypervisor gives to other virtual machines while yours waits. To run one properly, use YABS for a quick overview after reading the script, then repeat fixed fio, sysbench and iperf3 tests at least three times while you log steal time, and compare medians, not single runs.

This guide uses Ubuntu 24.04 LTS with the tool versions in Ubuntu’s repositories (fio 3.36, iperf3 3.16, sysbench 1.0.20) and YABS v2026-09-20, checked against each tool’s official documentation on October 3, 2026. It contains no benchmark results of ours: the sample output below is there to explain the format, and each sample says where it comes from.

Key takeaways

  • A VPS benchmark should measure CPU on one core and on all cores, 4K random disk IOPS with latency percentiles, 1M sequential throughput, network throughput to a far end you know, and steal time during every test.
  • Download yabs.sh, read it and record its checksum instead of piping curl into bash. A default run publishes a Geekbench result, sends your IP address to ip-api.com and can move up to about 35 GB over a fully used 1 Gbit/s port.
  • For disk tests, use a fio job file with direct=1, a test file rather than a device, and fixed queue depths, and read the 99th-percentile latency as well as the IOPS.
  • Run every test at least three times, report the median and the spread, and log vmstat's st column the whole time; steal time covers CPU only, so storage contention shows up as latency spread instead.
  • A one-hour benchmark on a server billed by the hour is billed as one hour; delete the server afterwards, because a stopped server is still billed.

What should a VPS benchmark measure?

One overall score hides the part that matters to your workload. A database cares about small random reads and their slowest responses, a build server about all cores at once, a game server about one fast core with steady timing, and a download mirror about throughput. Measure each part with a tool made for it:

PartWhat to measureToolUnitWhat it tells you
CPU, one coreSingle-thread speedsysbench, Geekbench single-coreevents/s, scoreOne request, one compile step, one game tick
CPU, all coresMulti-thread speed and how it scalessysbench on every vCPU, Geekbench multi-coreevents/s, scoreParallel builds, encoders, workers
MemoryBandwidth with a working set larger than the CPU cachesysbench memoryMiB/sCaches, in-memory data, large sorts
Disk, random4K random read and write IOPS at a deep queue; 4K read latency one request at a timefioIOPS, µs (median and 99th percentile)Databases, package installs, small files
Disk, sequential1M sequential read and writefioMB/sBackups, media, large files
Network, throughputTCP send and receive with several streamsiperf3Mbit/s, Gbit/sUploads, downloads, replication
Network, latencyRound-trip time and routeping, mtrmsHow responsive it feels to your users
ContentionSteal time during every testvmstat, mpstat, top% of CPU timeWhether other guests take CPU time you asked for
Units differ: iperf3 reports bits per second and fio reports bytes per second. 1 Gbit/s is 125 MB/s.

Latency has its own guide: how to measure VPS latency with ping, mtr and curl before you choose a location. This guide covers the rest.

How to run a VPS benchmark in 7 steps

  1. Deploy a fresh server with Ubuntu 24.04, in the location and on the plan you want to evaluate, never a production one: the fio write tests and iperf3 push the disk and the network port to their limits. Connect over SSH with a key and switch on the firewall from our VPS security checklist: a server with a public IP is reachable from the internet from its first minute.
  2. Record what you got: CPU model, vCPU count, RAM, disk, kernel and virtualization type.
  3. Install the tools, let package updates finish, and record one idle minute of vmstat as a baseline.
  4. Start logging steal time in a second session and leave it running through every test.
  5. Run YABS once for an overview, from a copy you have read, and save its JSON.
  6. Run the fixed tests three times each: the fio job file, sysbench on one core and on all cores, and iperf3 against a server you control.
  7. Summarize the medians and the spread, copy the results to your computer, then delete the server.

Steps 2 and 3: record the specs and install the tools

These commands print what the provider actually gave you. lscpu shows the CPU model the hypervisor exposes and a hypervisor vendor line; systemd-detect-virt prints kvm on a KVM server.

lscpu | grep -E 'Model name|^CPU\(s\)|Hypervisor'
nproc
free -h
df -h /
uname -r
systemd-detect-virt

Install the benchmark tools from Ubuntu’s repositories. sysstat provides mpstat, and tmux keeps long runs alive if your SSH connection drops:

sudo apt update
sudo apt install fio iperf3 sysbench sysstat tmux

When the iperf3 package asks “Start Iperf3 as a daemon automatically?”, answer No, which is the default. You will start the iperf3 server by hand only when you need it, so port 5201 isn’t left listening. If apt can’t find fio, iperf3 or sysbench, enable Ubuntu’s universe component with sudo add-apt-repository universe and run the two commands again.

Before you measure, make sure nothing else is busy. A fresh server may still be installing updates in the background, which skews disk and CPU numbers. Ubuntu runs its automatic updates from two systemd services; both should report inactive, and activating means updates are running, so wait and check again:

systemctl is-active apt-daily.service apt-daily-upgrade.service

Then take a one-minute idle baseline: 12 lines, one every 5 seconds. Ignore the first line; the vmstat manual says it shows averages since the last reboot.

vmstat -n -t 5 12

On an idle server, the st (steal) and wa (I/O wait) columns should sit at or near 0. If st is already high while nothing runs, the host is busy before your test starts: note it next to your results.

YABS: what the VPS benchmark script downloads and runs

Yet-Another-Bench-Script (YABS) is a popular one-command benchmark script. It runs fio for disk, iperf3 for network and Geekbench for CPU, and its README says it is designed to need no extra dependencies and no elevated privileges. Reading version v2026-09-20 of the script shows exactly what a default run does:

What it doesDetails, from the scriptFlag to change it
Looks up your networkChecks IPv4 and IPv6 (Google hosts or icanhazip.com), finds your address through ip6.me and sends it to ip-api.com over plain HTTP to print your ISP, ASN and city-n skips the lookup
Gets fio and iperf3Uses the system’s fio and iperf3 if they are installed; otherwise downloads prebuilt binaries from the YABS GitHub releases (latest release, with fio 3.42 and iperf3 3.21 as pinned fallbacks)-b forces the prebuilt binaries
Disk testA 2 GB test file in a temporary folder under the current directory; four 30-second random tests, 50% reads and 50% writes, at 4k, 64k, 512k and 1m blocks, queue depth 64, 2 jobs, direct I/O. Skipped with less than 2 GB free-f or -d skips it
Network testiperf3 with 8 parallel streams to 7 public servers (London, Amsterdam, Tashkent, Singapore, Los Angeles, New York, São Paulo), both directions, IPv4 and IPv6, up to 3 attempts each. The Ping column is one ping-r uses 3 servers (London, Singapore, New York); -i skips; -p sets your own servers
CPU testDownloads Geekbench 6 from cdn.geekbench.com (6.7.1 for x86_64 is about 228 MB) and runs it with --upload, so the result appears on the public Geekbench Browser; a claim link is saved to geekbench_claim.url-g skips; -4, -5 or -7 pick another version
Cleans upDeletes its temporary folder at the end or on Ctrl+C; geekbench_claim.url and your JSON file stay–
From yabs.sh v2026-09-20 and the YABS README, read October 3, 2026; the tarball size is the Content-Length cdn.geekbench.com reported that day. The README’s description of -r names different servers than the script; the script is what runs.

The network test is heavy by design: the README warns that it tries to fill the network port for about 20 seconds per location, 10 in each direction. The arithmetic: 7 servers × 2 directions × 10 seconds × 2 IP versions is 280 seconds of transfer, so up to about 35 GB on a fully used 1 Gbit/s port (280 s × 125 MB/s). With -r it is 120 seconds, or up to about 15 GB. On a faster port it can be roughly ten times as much, because the script labels most of its test servers 10G.

Traffic: Istanbul plans include the monthly traffic allowance listed for each plan, prorated for a server that exists for part of a billing period. A short-lived server gets a small share: Quartz Q2’s 3 TB a month is about 4 GB per hour of a 30-day month (our arithmetic), while a full 1 Gbit/s test moves about 1.25 GB every 10 seconds. Above its share, our network page says a server’s port speed may be limited for the rest of the period, which would also skew every later test. On an Istanbul server, skip YABS’s network test with -i and keep your own iperf3 runs short.

Download YABS, read it, then run it

The README’s quick start pipes the script straight into bash: curl -sL yabs.sh | bash. That runs whatever the server sends at that moment, without anyone reading it, and the yabs.sh domain only redirects to the current script on GitHub. The README’s own security notice says:

Use this script at your own risk as you would with any script publicly available on the net.

YABS README, “Security Notice”

Download the file instead, record its checksum so you know which version produced your numbers, and read it:

curl -fsSL https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh -o yabs.sh
sha256sum yabs.sh
less yabs.sh

In less, type / and then curl, wget or http to jump to every address the script contacts. Then print the help screen, which lists the flags, shows whether a local fio and iperf3 were found, and exits without testing:

bash yabs.sh -h

Run it from your home folder inside tmux, so a dropped SSH connection doesn’t stop it. This run uses the three-server network test and writes the results to a JSON file; on a server with a small traffic share, use -i instead of -r:

tmux new -s bench
bash yabs.sh -r -w yabs-run1.json

To leave tmux running in the background, press Ctrl+B, then D. Reattach later with tmux attach -t bench.

Don’t add -s unless you mean to publish. The -s flag sends the JSON results to the URLs you give it, such as the community databases listed in the README. That JSON includes your CPU model, RAM and disk size, and the ISP, ASN and city from the network lookup.

Flags combine: -fg runs only the network test, -w file saves the results as JSON and -j prints them as JSON.

Two things to check before you compare your YABS numbers with someone else’s. First, local packages take precedence: a server with Ubuntu’s fio 3.36 installed and one without it run different fio versions, and -b makes both use the prebuilt binaries. Second, YABS’s disk figures come from 50/50 mixed read/write tests, so they can’t be compared with a pure random-read IOPS figure such as the one from the fio job below.

On a 1 GB server such as Quartz Q1, the Geekbench 6 step can fail for lack of memory. The script then suggests adding at least 1 GB of swap or running Geekbench 4 with -4; our guide to adding swap on Ubuntu 24.04 covers the first option. A plan with 2 GB of RAM, such as Quartz Q2, is above the 1 GB mark the script checks for.

YABS vs bench.sh and UnixBench

YABS isn’t the only one-command VPS benchmark script. Read any of them before you run it, and check what it actually measures:

ScriptWhat it runsWhat to keep in mind
bench.sh (Teddysun, v2026-01-31)A 1 GiB sequential write with dd (512 KiB blocks, conv=fdatasync), three times, averaged; Ookla’s Speedtest CLI to a server it picks itself plus 11 fixed onesOne sequential write stream: no random I/O and no latency percentiles. It passes --accept-license --accept-gdpr to Speedtest for you, so read Ookla’s terms first
UnixBench (byte-unixbench)A suite of system tests, run once with one copy and once with one copy per CPU, scored as an index against a baseline systemIts README calls it “a system benchmark, not a CPU, RAM or disk benchmark”; results also depend on the OS, libraries and compiler
From the bench.sh source and the byte-unixbench README, read October 3, 2026.

How to test VPS disk speed with fio

Running fio, the Flexible I/O tester, yourself lets you pick the patterns that match your workload instead of YABS’s mixed tests. The job file below runs five tests one after another, each for 60 seconds after a 10-second warm-up: 4K random reads and 4K random writes at a deep queue, to find the IOPS ceiling; 4K random reads one at a time, to see the latency of a single request; and 1M sequential reads and writes, for throughput.

Point fio at a file, never at a device. With filename=/dev/vda or similar, the write tests overwrite the disk your system runs on. The job file below uses a 4 GiB file in the current folder, so check that you have at least that much free with df -h . first.

The fio job file

Create a folder for the results and open a new job file:

mkdir -p ~/bench && cd ~/bench
nano vps-bench.fio

Paste this and save it:

; vps-bench.fio - five disk tests, run one after another
[global]
ioengine=libaio
direct=1
filename=fio-testfile
size=4G
time_based=1
runtime=60
ramp_time=10
group_reporting=1

[rand-read-4k]
rw=randread
bs=4k
iodepth=32
numjobs=4
stonewall

[rand-write-4k]
rw=randwrite
bs=4k
iodepth=32
numjobs=4
stonewall

[rand-read-4k-qd1]
rw=randread
bs=4k
iodepth=1
numjobs=1
stonewall

[seq-read-1m]
rw=read
bs=1M
iodepth=8
numjobs=1
stonewall

[seq-write-1m]
rw=write
bs=1M
iodepth=8
numjobs=1
stonewall

Run it three times and keep each run’s results as JSON. One pass takes about six minutes, plus the time fio needs to create the 4 GiB file on the first pass:

for i in 1 2 3; do fio vps-bench.fio --output-format=json --output=fio-run$i.json; done

The same options work on the command line. This runs the deep-queue random-read test alone, with fio’s normal text output:

fio --name=rand-read-4k --filename=fio-testfile --size=4G --ioengine=libaio --direct=1 --rw=randread --bs=4k --iodepth=32 --numjobs=4 --time_based --runtime=60 --ramp_time=10 --group_reporting

When you’re finished with disk tests, delete the test file: rm ~/bench/fio-testfile.

What each fio option does

OptionValue hereWhat it does
ioenginelibaioLinux native asynchronous I/O; the fio docs note that Linux may only queue requests with non-buffered I/O, hence direct=1
direct1Non-buffered I/O (usually O_DIRECT): skips your server’s page cache, so you measure the virtual disk, not RAM
rwrandread, randwrite, read, writeRandom or sequential; reads or writes
bs4k, 1MBlock size: small blocks for IOPS, large blocks for throughput
iodepth32, 1, 8Requests in flight per job: 32 × 4 jobs keeps 128 outstanding to find the ceiling; 1 shows single-request latency
numjobs4 or 1Clones of the job, each an independent process
group_reportingonReports each test as one total instead of one block per clone
size4GAmount of file I/O per job; every job here uses the same fio-testfile
time_based + runtime60 sRuns the full 60 seconds, looping over the file if needed
ramp_time10 sWarm-up before logging starts; adds to the total time
stonewallon each jobWaits for the previous job and starts a new reporting group, so the tests run one at a time
Option meanings from the fio documentation (rev. 3.42); Ubuntu 24.04’s fio 3.36 supports all of them.

How to read fio output

In the normal text output, each test prints a block like the one below. This is the example from the fio documentation, trimmed to the lines discussed here; it is not a VPS result:

Client1: (groupid=0, jobs=1): err= 0: pid=16109: Sat Jun 24 12:07:54 2017
  write: IOPS=88, BW=623KiB/s (638kB/s)(30.4MiB/50032msec)
    clat (usec): min=170, max=78367, avg=4019.02, stdev=8293.31
    clat percentiles (usec):
     |  1.00th=[  302],  5.00th=[  326], 10.00th=[  343], 20.00th=[  363],
     | 30.00th=[  392], 40.00th=[  404], 50.00th=[  416], 60.00th=[  445],
     | 70.00th=[  816], 80.00th=[ 6718], 90.00th=[12911], 95.00th=[21627],
     | 99.00th=[43779], 99.50th=[51643], 99.90th=[68682], 99.95th=[72877],
     | 99.99th=[78119]
  IO depths    : 1=85.0%, 2=13.1%, 4=1.8%, 8=0.1%, 16=0.0%, 32=0.0%, >=64=0.0%
  • IOPS and BW: average operations per second and bandwidth, in power-of-2 units (KiB/s) with the power-of-10 value (kB/s) in brackets.
  • clat percentiles: completion latency. Compare the 50th percentile, the typical request, with the 99th and 99.9th, the slow tail. In the documentation’s example the median is 416 µs and the 99th percentile 43,779 µs: the kind of tail that makes a database feel slow while the average looks fine.
  • IO depths: the docs advise checking that the depth fio achieved matches the one you set. A queue-depth-32 test with nearly all I/O at depth 1 means the queue isn’t filling, for example because direct=1 is missing.
  • err= should be 0. Anything else means the test failed.

How to benchmark VPS CPU and memory with sysbench and Geekbench

sysbench: one core, then all cores

The sysbench CPU test checks numbers for primality up to a limit (--cpu-max-prime, 10,000 by default) in a loop and counts how many loops per second the threads finish. Each event is a short trial-division loop that fits in the CPU cache, so it measures raw core speed and scaling, not memory. Run it on one thread, then on every vCPU:

sysbench cpu --threads=1 --time=30 run
sysbench cpu --threads="$(nproc)" --time=30 run

Read the events per second line under CPU speed:, then divide the all-core figure by the one-core figure. That ratio shows how well the plan scales across its vCPUs; compare it between plans rather than against a fixed target. A ratio that drops from run to run while steal time rises points at contention. Compare sysbench numbers only across the same sysbench version and --cpu-max-prime.

Memory bandwidth: sysbench memory, with a large block

sysbench also has a memory test, but its defaults measure the CPU cache, not RAM. In the sysbench 1.0.20 source, the test reads or writes one buffer of --memory-block-size over and over, and the default block is 1 KiB, small enough to stay in the fastest cache. For a RAM figure, first check the L3 cache size the server reports:

lscpu | grep L3

Then pick a block well above it. The block size must be a power of two: 1G suits a server with 4 GB of RAM or more, and 512M a 2 GB server. This run reads; write is the default, so run it once without --memory-oper as well:

sysbench memory --memory-block-size=1G --memory-oper=read --threads="$(nproc)" run

Read the MiB/sec figure on the MiB transferred line. The test stops after 100 GiB in total or 10 seconds, whichever comes first. Treat memory bandwidth as supporting evidence next to the CPU and disk numbers, and compare it only between runs with the same block size, operation and thread count.

Geekbench: scores you can compare, uploaded in public

Geekbench runs real-world workloads and reports a single-core and a multi-core score that you can compare with the many results people publish. Two things to know first:

  • Free results are public. Primate Labs’ editions page lists online results on the Geekbench Browser for the free edition. Saving results offline, so they never appear on the Browser, is a Geekbench Pro feature, along with command-line automation tools and a commercial-use license. If you benchmark servers for an employer or for clients, read the license terms first.
  • Stay on one major version. Each major version uses its own set of workloads (Primate Labs describes Geekbench 7’s workloads as updated), so compare 6 with 6 and 7 with 7. YABS runs Geekbench 6 by default and Geekbench 7 with -7.

To run it without YABS, download the Linux tarball and start the binary with uploads on, as YABS does. This is the Geekbench 6.7.1 build that YABS v2026-09-20 downloads; check Geekbench’s Linux download page for the current release:

curl -fLO https://cdn.geekbench.com/Geekbench-6.7.1-Linux.tar.gz
tar xzf Geekbench-6.7.1-Linux.tar.gz
cd Geekbench-6.7.1-Linux
./geekbench6 --upload

The download is about 228 MB, and according to the YABS script, cdn.geekbench.com serves it over IPv4 only. When the run ends, the result link on the Geekbench Browser carries the full breakdown.

How to test VPS network speed with iperf3

iperf3 measures TCP throughput between two machines: one runs as the server, the other as the client. The result describes the whole path, so it depends on the far end as much as on your VPS. Ubuntu 24.04 ships iperf3 3.16, the first version that runs each parallel stream in its own thread, according to the iperf3 FAQ.

Test only between servers you control, or against public servers whose operators invite tests. Our acceptable use policy forbids flooding any network or system with traffic.

The fair test: your own iperf3 server

Deploy a second server for the session and test between the two. Nothing else shares the far end, and you know its port speed. To see the path your users get, also run the client from a machine near them. On the far server (198.51.100.20 in this example), allow the iperf3 port from the client’s address only, then start iperf3 in the foreground:

sudo ufw allow from 203.0.113.10 to any port 5201 proto tcp
iperf3 -s

On the server you’re benchmarking (203.0.113.10), run a 10-second test with four parallel streams, then the same test in reverse:

iperf3 -c 198.51.100.20 -P 4 -t 10 -O 3
iperf3 -c 198.51.100.20 -P 4 -t 10 -O 3 -R
FlagMeaning
-sRun as the server; it listens on TCP port 5201 by default
-c hostRun as a client and connect to that server
-P 4Four parallel streams; since iperf3 3.16 each gets its own thread
-t 10Test for 10 seconds, the default; at a full 1 Gbit/s that is about 1.25 GB per direction
-O 3Run 3 seconds first and leave them out of the results, to skip TCP slow start
-RReverse: the server sends and the client receives
-JJSON output instead of text
From the iperf3 manual (iperf3 3.22 documentation); all of these exist in Ubuntu 24.04’s iperf3 3.16.

Read the [SUM] lines at the end. Per the manual, the final summary shows the test as seen by both sender and receiver, tagged accordingly; quote the receiver figure, which counts what arrived. When you’re done, stop the server with Ctrl+C and remove the rule:

sudo ufw delete allow from 203.0.113.10 to any port 5201 proto tcp

For reference, Quartz plans have a 1 Gbit/s port and Chrono plans a 25 Gbit/s port, as our network page lists. A test between two servers can only be as fast as the slower port, and a test across an ocean measures the path as much as either port.

Public iperf3 servers: useful, with caveats

Public servers, which YABS uses, are convenient when you have no second machine. Keep their limits in mind:

  • One test at a time. The public server list at iperf.fr notes that iperf3 servers accept one connection at a time; a busy one answers “the server is busy running a test. try again later”. YABS retries up to three times per direction and prints “busy” when it gets no result.
  • The far end is a stranger. Its uplink, its load and the route to it are part of every number, so a slow result says little about your VPS.
  • Distance changes the result. Over a long round trip, a single TCP stream rarely fills a fast port, so more streams (-P) usually report more. YABS’s 8-stream figures are not comparable with a 1-stream test.
  • Keep it short. These servers are a courtesy from the people who run them: use the default 10 seconds, don’t loop tests, and keep to the ports each operator lists.

How do you check steal time and noisy neighbors on a VPS?

Steal time is CPU time your server wanted but didn’t get, because the hypervisor was running another virtual machine. The vmstat manual defines its st column as “Time stolen from a virtual machine”, and the top manual calls it “time stolen from this vm by the hypervisor”. For a quick look, read st in the %Cpu(s) line of top. Steal covers CPU only: a neighbor hammering shared storage shows up instead as a wider gap between fio’s median and 99th-percentile latency, and as a bigger spread between runs.

Log steal time for the whole session. In a second SSH session or tmux window, start this before your first test and stop it with Ctrl+C after the last one:

vmstat -n -t 5 | tee ~/bench/vmstat.log

-n prints the header once and -t timestamps each line, so you can match a spike to the test that was running. mpstat from the sysstat package shows steal per vCPU; its manual defines %steal as time “spent in involuntary wait by the virtual CPU or CPUs while the hypervisor was servicing another virtual processor”.

mpstat -P ALL 5

After the session, this prints the number of samples, the average and the highest steal in the log. It finds the st column by name and skips the first data line, the average since boot:

awk 'NR==2 {for (i=1; i<=NF; i++) if ($i=="st") c=i} NR>3 && c {s+=$c; n++; if ($c>m) m=$c} END {if (n) printf "%d samples, average st %.1f%%, max st %d%%\n", n, s/n, m}' ~/bench/vmstat.log

There is no official threshold. Our rule of thumb, the same one in our guide to shared and dedicated vCPUs: a few percent now and then is normal on shared vCPUs, while a steady double-digit share during the hours you care about means the job needs dedicated cores. On dedicated, pinned vCPUs, steal should stay close to zero; if it doesn’t, ask the provider why.

At HourlyVPS, Quartz plans share their vCPUs and Chrono plans have dedicated, pinned vCPUs; our network page explains both and notes that we haven’t published a contention ratio for Quartz yet. The acceptable use policy lets us limit the CPU of a Quartz server that runs its shared vCPUs at full load for long periods; for hours of sustained CPU work, Chrono is the family built for it.

How to read VPS benchmark results and compare providers fairly

A benchmark tells you what the server can do with synthetic work. Whether your application keeps up under real traffic is a different question, answered by a load test: see load testing with k6 from a VPS.

Run-to-run variance: repeat and report the spread

One run is an anecdote. Virtual machines share hosts, storage and network paths, so the same test can return different numbers minutes apart. Run each test at least three times, report the median rather than the fastest run, and report the spread: (highest − lowest) ÷ median. A wide spread on a shared-vCPU plan together with steal time is the noisy-neighbor pattern; a wide spread in disk latency with no steal points at shared storage.

This Python script reads the three fio JSON files and prints, per test, the median IOPS, the spread, the median MB/s and the median 99th-percentile latency in microseconds. It needs only the standard library, so Ubuntu 24.04’s python3 runs it. Save it as fio_summary.py in ~/bench:

#!/usr/bin/env python3
"""Median and spread of fio JSON results across runs (fio --output-format=json)."""
import json
import statistics
import sys
from collections import defaultdict

runs = defaultdict(lambda: {"iops": [], "mbs": [], "p99": []})

for path in sys.argv[1:]:
    with open(path) as f:
        data = json.load(f)
    for job in data["jobs"]:
        for direction in ("read", "write"):
            d = job[direction]
            if d["io_bytes"] == 0:
                continue
            r = runs[job["jobname"] + " " + direction]
            r["iops"].append(d["iops"])
            r["mbs"].append(d["bw_bytes"] / 1e6)
            r["p99"].append(d["clat_ns"].get("percentile", {}).get("99.000000", 0) / 1000)

print(f"{'job':26} {'runs':>4} {'IOPS':>9} {'spread':>7} {'MB/s':>8} {'p99 us':>8}")
for name, r in runs.items():
    med = statistics.median(r["iops"])
    spread = (max(r["iops"]) - min(r["iops"])) / med * 100 if med else 0
    print(f"{name:26} {len(r['iops']):>4} {med:>9.0f} {spread:>6.1f}% "
          f"{statistics.median(r['mbs']):>8.1f} {statistics.median(r['p99']):>8.0f}")
python3 fio_summary.py fio-run*.json

The key names come from fio’s JSON output: iops, bw_bytes and the clat_ns percentiles, which are in nanoseconds. To catch time-of-day effects, repeat the whole set at a different hour or on another day; on a shared host, your results change with your neighbors’ schedules.

A fair-comparison checklist

Keep the sameWhy
Starting point: a fresh, idle server, same OS image and kernel (uname -r)Background jobs, kernels and drivers all move disk and network results
Plan class: shared or dedicated vCPU, vCPU count, RAMTwo shared vCPUs and two dedicated vCPUs are different products
Tool versions: fio, iperf3, sysbench, Geekbench major versionDifferent versions give different numbers
Test parameters: block size, queue depth, jobs, file size, runtimeYABS’s 50/50 mixed 4k figure is not a random-read figure
Network far end: the same iperf3 server, distance and stream countThe path is part of every network number
Timing: the same hours, at least three runs eachShared hosts vary with the neighbors’ load
Billing mode when you compare price per resultHourly with hourly, monthly with monthly; the Hourly VPS Fine-Print Index lists each provider’s terms
Write each item down next to your results, with the date, the location and the plan name.

When VPS benchmark results look wrong

SymptomLikely causeWhat to do
YABS prints “busy” for a locationThe public iperf3 server was running someone else’s test, or didn’t answerRerun later, use -r, or point -p at your own server
YABS: “Less than 2GB of space available. Skipping disk test…”Not enough free space in the current folderFree some space, or run it from a bigger filesystem
Geekbench fails on a 1 GB serverToo little memory; YABS checks for 1 GB or lessAdd at least 1 GB of swap, or use -4
fio numbers far above anything the disk could dodirect=1 is missing, so reads come from RAMAdd direct=1 and rerun
Queue depth 32 barely beats queue depth 1The queue isn’t filling, or the plan has an IOPS limitCheck the IO depths line and direct=1; compare with a second run
Second run much slower than the firstContention, or a limit that applies after sustained loadCheck vmstat.log for steal; pause and rerun; report the spread
iperf3 far below the port speed to a distant serverLong round trip, or a slow far endUse -P 4, test a closer server, or use your own far end
Receiver total lower than sender in a short testData still in flight when the test ended, as the iperf3 FAQ explainsUse a longer -t
YABS messages from yabs.sh v2026-09-20; iperf3 behavior from the iperf3 FAQ; fio options from the fio documentation.

What does a one-hour VPS benchmark cost?

A full session fits in about an hour if nothing needs investigating:

TimeStep
0:00–0:10Deploy, connect, record the specs, install the tools, idle baseline
0:10–0:25YABS with -r or -i, from a copy you have read
0:25–0:45The fio job file, three passes
0:45–0:50sysbench CPU on one core and on all cores, three times each; sysbench memory, read and write
0:50–0:55iperf3 to your own second server, both directions
0:55–1:00Summarize, copy the results off, delete both servers
A sample plan. The fio and sysbench durations come from the commands above; YABS’s duration depends on the network test and Geekbench.

One hour: $0.02 on Quartz Q2, whose 2 GB of RAM clears the 1 GB mark at which YABS flags Geekbench memory failures, or $0.07 on Chrono C8 with dedicated vCPUs. The iperf3 far end adds its own hour: $0.01 on Quartz Q1, whose 1 Gbit/s port caps the test, or a second Chrono C8 to see past 1 Gbit/s. At 25 Gbit/s, though, 10 seconds is about 31 GB, so read the traffic note above first. Billing is by the hour: every hour a server exists is charged at the plan’s hourly rate. The price tapes and cost tables on this site count every started hour as a full hour, so they show the most a duration can cost; the cost calculator charges a partial hour to the nearest cent, as the bill does.

Chrono C8 (2 dedicated vCPU, 8 GB RAM): a benchmark session by duration, billed by the hour and capped at the monthly price
DurationHours on the meterCost $0.07/hour · cap $35.00/monthNote
1 hour1$0.07
3 hours3$0.21
1 day24$1.68
3 days72$5.04
7 days168$11.76
Charges stop at $35.00 after 500 hours (about 20.8 days) in a billing period; the rest of that period is free.

If you keep the server longer to rerun the tests at other hours, a day is 24 hours of the same hourly billing, $1.68 on Chrono C8 (see renting a VPS by the day), and a server left running never costs more than $35.00 in a billing period (one month from your order date), the plan’s monthly cap. Our guide to how hourly billing and the monthly cap work has worked examples, and all sizes are on the pricing page.

When you’re done, copy the ~/bench folder to your computer, then delete the server. A stopped server is still billed, because its vCPU, memory, disk and IP addresses stay reserved for you; only deleting the server stops billing. Run this on your computer:

scp -r [email protected]:bench ./vps-bench-results

Our checklist before you delete a VPS covers anything else worth keeping.

How other providers bill a 20-minute benchmark

If your tests take 20 minutes, the billing unit decides whether you pay for 20 minutes or for an hour. These are the units in the Hourly VPS Fine-Print Index, as of October 2026:

ProviderBilling unitA 20-minute test is billed as
HourlyVPSPer hour; a partial first or last hour is rounded to the nearest cent20 minutes, rounded to the nearest cent
Hetzner CloudPer hour, always rounded up1 hour
VultrPer hour, 1-hour minimum1 hour
Akamai (Linode)Per hour, rounded up1 hour
UpCloudPer started hour1 hour
Microsoft AzurePer full minute20 minutes
DigitalOceanPer second; minimum 60 seconds or one cent, whichever is higher20 minutes
Google Compute EnginePer second after a 1-minute minimum20 minutes
OVHcloud Public CloudPer second after a 1-minute minimum20 minutes
Billing units from the Hourly VPS Fine-Print Index; each was checked on the provider’s own page on October 2, 2026. This compares the unit only: hourly rates differ, so a per-hour provider can still cost less for the same test.

Per-second and per-minute billing is the better fit if you run many short tests, for example ten 10-minute runs on fresh servers: each is billed for 10 minutes, where a per-hour provider bills ten hours. Our guide to per-second vs per-hour billing works through more cases, and the Fine-Print Index has every provider’s source.

Deploy this setup

Benchmark a VPS for an hour, then delete it

Chrono C8 · 2 dedicated vCPU · 8 GB RAM · 100 GB NVMe · Istanbul

  • Per hour$0.07/hourFor this job
  • Per day (24 h)$1.68/day
  • Monthly cap$35.00/month
Deploy Chrono C8

Starts with a $5 initial credit, which goes into the server’s balance and pays for its hours.

Billed by the hour, never more than $35.00 per billing period. Delete the server and billing stops.

FAQ

Is it safe to run YABS?

YABS is open source, so you can read every line before you run it. Piping curl into bash skips that step and runs whatever the server sends; download yabs.sh, read it, note its sha256sum and run it with bash instead. Its own README says to use it at your own risk.

How long does a VPS benchmark take?

The README's sample YABS run, which included three Geekbench versions, finished in 12 minutes 49 seconds. The fio job file in this guide takes about six minutes per pass, so three passes plus YABS, sysbench, iperf3 and setup fit in about an hour.

Is Geekbench free, and are my results public?

Running Geekbench is free, and in the free edition results go to the public Geekbench Browser; YABS runs it with uploads on. Primate Labs lists offline results, command-line automation tools and commercial use as Geekbench Pro features.

What is a normal steal time on a VPS?

There is no official threshold. As a rule of thumb, a few percent now and then is normal on shared vCPUs, while a steady double-digit share during your busy hours means the workload needs dedicated vCPUs. On dedicated, pinned vCPUs it should stay close to zero.

Why do my VPS benchmark results change between runs?

Virtual machines share hosts, storage and network paths, so neighbors' load, the far end of a network test and background jobs all move the numbers. Run each test at least three times, compare medians and record the spread, and log steal time while you test.

Can I benchmark a VPS without root?

Yes. YABS is designed to run without elevated privileges, and fio, sysbench and the iperf3 client all run as a normal user against files in your home folder. Only installing packages with apt and changing firewall rules need sudo.

What is the difference between a VPS benchmark and a load test?

A benchmark measures what the server itself can do, using synthetic CPU, disk and network work. A load test sends simulated users to your application to see how it behaves under traffic, with a tool such as k6 run from a separate machine.

Sources

  1. Yet-Another-Bench-Script README (flags, tests, security notice)Mason Rowe on GitHub · github.com · checked
  2. yabs.sh v2026-09-20 (downloads, fio and iperf3 parameters, Geekbench upload)Mason Rowe on GitHub · github.com · checked
  3. fio – Flexible I/O tester documentation (rev. 3.42)fio project · fio.readthedocs.io · checked
  4. Invoking iperf3 (manual page, iperf3 3.22)ESnet · software.es.net · checked
  5. iperf3 FAQ (multi-threading since 3.16, short-test byte counts)ESnet · software.es.net · checked
  6. Public iPerf3 serversiperf.fr · iperf.fr · checked
  7. Geekbench 7 editions (free vs Pro features)Primate Labs · geekbench.com · checked
  8. sysbench README and test sources (cpu, memory)Alexey Kopytov on GitHub · github.com · checked
  9. vmstat(8) manual page (st column)procps-ng via man7.org · man7.org · checked
  10. mpstat(1) manual page (%steal)sysstat via man7.org · man7.org · checked
All posts