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:
| Part | What to measure | Tool | Unit | What it tells you |
|---|---|---|---|---|
| CPU, one core | Single-thread speed | sysbench, Geekbench single-core | events/s, score | One request, one compile step, one game tick |
| CPU, all cores | Multi-thread speed and how it scales | sysbench on every vCPU, Geekbench multi-core | events/s, score | Parallel builds, encoders, workers |
| Memory | Bandwidth with a working set larger than the CPU cache | sysbench memory | MiB/s | Caches, in-memory data, large sorts |
| Disk, random | 4K random read and write IOPS at a deep queue; 4K read latency one request at a time | fio | IOPS, µs (median and 99th percentile) | Databases, package installs, small files |
| Disk, sequential | 1M sequential read and write | fio | MB/s | Backups, media, large files |
| Network, throughput | TCP send and receive with several streams | iperf3 | Mbit/s, Gbit/s | Uploads, downloads, replication |
| Network, latency | Round-trip time and route | ping, mtr | ms | How responsive it feels to your users |
| Contention | Steal time during every test | vmstat, mpstat, top | % of CPU time | Whether other guests take CPU time you asked for |
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
- 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.
- Record what you got: CPU model, vCPU count, RAM, disk, kernel and virtualization type.
- Install the tools, let package updates finish, and record one idle minute of
vmstatas a baseline. - Start logging steal time in a second session and leave it running through every test.
- Run YABS once for an overview, from a copy you have read, and save its JSON.
- 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.
- 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-virtInstall 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 tmuxWhen 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.serviceThen 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 12On 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 does | Details, from the script | Flag to change it |
|---|---|---|
| Looks up your network | Checks 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 iperf3 | Uses 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 test | A 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 test | iperf3 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 test | Downloads 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_ | -g skips; -4, -5 or -7 pick another version |
| Cleans up | Deletes its temporary folder at the end or on Ctrl+C; geekbench_ and your JSON file stay | – |
-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.shIn 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 -hRun 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.jsonTo 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:
| Script | What it runs | What to keep in mind |
|---|---|---|
| bench.sh (Teddysun, v2026-01-31) | A 1 GiB sequential write with dd (512 KiB blocks, conv=), three times, averaged; Ookla’s Speedtest CLI to a server it picks itself plus 11 fixed ones | One 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 system | Its README calls it “a system benchmark, not a CPU, RAM or disk benchmark”; results also depend on the OS, libraries and compiler |
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.fioPaste 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
stonewallRun 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; doneThe 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_reportingWhen you’re finished with disk tests, delete the test file: rm ~/bench/fio-testfile.
What each fio option does
| Option | Value here | What it does |
|---|---|---|
ioengine | libaio | Linux native asynchronous I/O; the fio docs note that Linux may only queue requests with non-buffered I/O, hence direct= |
direct | 1 | Non-buffered I/O (usually O_DIRECT): skips your server’s page cache, so you measure the virtual disk, not RAM |
rw | randread, randwrite, read, write | Random or sequential; reads or writes |
bs | 4k, 1M | Block size: small blocks for IOPS, large blocks for throughput |
iodepth | 32, 1, 8 | Requests in flight per job: 32 × 4 jobs keeps 128 outstanding to find the ceiling; 1 shows single-request latency |
numjobs | 4 or 1 | Clones of the job, each an independent process |
group_ | on | Reports each test as one total instead of one block per clone |
size | 4G | Amount of file I/O per job; every job here uses the same fio-testfile |
time_ + runtime | 60 s | Runs the full 60 seconds, looping over the file if needed |
ramp_ | 10 s | Warm-up before logging starts; adds to the total time |
stonewall | on each job | Waits for the previous job and starts a new reporting group, so the tests run one at a time |
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=1is 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 runRead 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 L3Then 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)" runRead 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 --uploadThe 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 -sOn 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| Flag | Meaning |
|---|---|
-s | Run as the server; it listens on TCP port 5201 by default |
-c host | Run as a client and connect to that server |
-P 4 | Four parallel streams; since iperf3 3.16 each gets its own thread |
-t 10 | Test for 10 seconds, the default; at a full 1 Gbit/s that is about 1.25 GB per direction |
-O 3 | Run 3 seconds first and leave them out of the results, to skip TCP slow start |
-R | Reverse: the server sends and the client receives |
-J | JSON output instead of text |
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 tcpFor 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 5After 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.logThere 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*.jsonThe 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 same | Why |
|---|---|
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, RAM | Two shared vCPUs and two dedicated vCPUs are different products |
| Tool versions: fio, iperf3, sysbench, Geekbench major version | Different versions give different numbers |
| Test parameters: block size, queue depth, jobs, file size, runtime | YABS’s 50/50 mixed 4k figure is not a random-read figure |
| Network far end: the same iperf3 server, distance and stream count | The path is part of every network number |
| Timing: the same hours, at least three runs each | Shared hosts vary with the neighbors’ load |
| Billing mode when you compare price per result | Hourly with hourly, monthly with monthly; the Hourly VPS Fine-Print Index lists each provider’s terms |
When VPS benchmark results look wrong
| Symptom | Likely cause | What to do |
|---|---|---|
| YABS prints “busy” for a location | The public iperf3 server was running someone else’s test, or didn’t answer | Rerun 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 folder | Free some space, or run it from a bigger filesystem |
| Geekbench fails on a 1 GB server | Too little memory; YABS checks for 1 GB or less | Add at least 1 GB of swap, or use -4 |
| fio numbers far above anything the disk could do | direct= is missing, so reads come from RAM | Add direct= and rerun |
| Queue depth 32 barely beats queue depth 1 | The queue isn’t filling, or the plan has an IOPS limit | Check the IO depths line and direct=; compare with a second run |
| Second run much slower than the first | Contention, or a limit that applies after sustained load | Check vmstat. for steal; pause and rerun; report the spread |
| iperf3 far below the port speed to a distant server | Long round trip, or a slow far end | Use -P 4, test a closer server, or use your own far end |
| Receiver total lower than sender in a short test | Data still in flight when the test ended, as the iperf3 FAQ explains | Use a longer -t |
What does a one-hour VPS benchmark cost?
A full session fits in about an hour if nothing needs investigating:
| Time | Step |
|---|---|
| 0:00–0:10 | Deploy, connect, record the specs, install the tools, idle baseline |
| 0:10–0:25 | YABS with -r or -i, from a copy you have read |
| 0:25–0:45 | The fio job file, three passes |
| 0:45–0:50 | sysbench CPU on one core and on all cores, three times each; sysbench memory, read and write |
| 0:50–0:55 | iperf3 to your own second server, both directions |
| 0:55–1:00 | Summarize, copy the results off, delete both servers |
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.
| Duration | Hours on the meter | Cost $0.07 | Note |
|---|---|---|---|
| 1 hour | 1 | $0.07 | |
| 3 hours | 3 | $0.21 | |
| 1 day | 24 | $1.68 | |
| 3 days | 72 | $5.04 | |
| 7 days | 168 | $11.76 |
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-resultsOur 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:
| Provider | Billing unit | A 20-minute test is billed as |
|---|---|---|
| HourlyVPS | Per hour; a partial first or last hour is rounded to the nearest cent | 20 minutes, rounded to the nearest cent |
| Hetzner Cloud | Per hour, always rounded up | 1 hour |
| Vultr | Per hour, 1-hour minimum | 1 hour |
| Akamai (Linode) | Per hour, rounded up | 1 hour |
| UpCloud | Per started hour | 1 hour |
| Microsoft Azure | Per full minute | 20 minutes |
| DigitalOcean | Per second; minimum 60 seconds or one cent, whichever is higher | 20 minutes |
| Google Compute Engine | Per second after a 1-minute minimum | 20 minutes |
| OVHcloud Public Cloud | Per second after a 1-minute minimum | 20 minutes |
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
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.



