sysbench is a scriptable benchmarking tool that measures CPU, memory, file I/O and database performance with repeatable, synthetic workloads. It is useful to compare two server plans, check whether a configuration change helped, or keep a baseline to detect performance regressions later. In this tutorial you will install sysbench on Ubuntu 24.04, run CPU, memory, disk and MySQL OLTP benchmarks, learn which numbers matter in each result, and save a baseline you can rerun.

Prerequisites

To follow this guide you need:

  • A server running Ubuntu 24.04 LTS, such as a CubePath VPS, and a non-root user with sudo privileges.
  • At least 10 GB of free disk space on the filesystem you want to test, for the file I/O test files.
  • For the database benchmark (Step 5): MySQL Server, which you will install in that step, or an existing test instance. Never run the OLTP benchmark against a production database.

Benchmark on an otherwise idle server. Other workloads running at the same time will distort the results, and the tests themselves put a heavy load on the machine.

Step 1 - Installing sysbench

sysbench is in the Ubuntu universe repository:

sudo apt update
sudo apt install sysbench

Check the version:

sysbench --version
sysbench 1.0.20

Before running any test, write down the basic hardware facts so you can put the results in context later:

nproc
lscpu | grep -E 'Model name|^CPU\(s\)'
free -h
df -h /

Step 2 - Benchmarking the CPU

The CPU test verifies prime numbers up to a limit (--cpu-max-prime, 10000 by default) in a loop. Each completed verification is an event, so the key metric is events per second. Start with a single thread to measure per-core speed, which is what single-threaded software such as many PHP or Node.js requests depends on:

sysbench cpu --threads=1 --time=30 run
CPU speed:
    events per second:  1482.36

General statistics:
    total time:                          30.0003s
    total number of events:              44472

Latency (ms):
         min:                                    0.66
         avg:                                    0.67
         max:                                    1.43
         95th percentile:                        0.69
         sum:                                29988.21

Then run one thread per vCPU to measure the whole machine:

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

On a server with 4 dedicated vCPUs, the multi-threaded result should be close to 4 times the single-thread result. A much smaller ratio suggests CPU contention, thermal or power limits, or hyperthreaded sibling cores sharing execution units.

Only compare CPU results that used the same --cpu-max-prime value and the same sysbench version, since both change the amount of work per event.

Step 3 - Benchmarking memory bandwidth

The memory test writes (by default) blocks of memory in a loop and reports the throughput. Use 1 MB blocks to measure bandwidth:

sysbench memory --memory-block-size=1M --memory-total-size=50G --threads=1 run
Total operations: 51200 (8712.44 per second)

51200.00 MiB transferred (8712.44 MiB/sec)

The key metric is the MiB/sec figure. The test stops when it has transferred --memory-total-size or after 10 seconds, whichever comes first. Repeat with all threads to see aggregate bandwidth:

sysbench memory --memory-block-size=1M --memory-total-size=100G --threads=$(nproc) run

To measure reads instead of writes, add --memory-oper=read. Small blocks (for example --memory-block-size=4K) measure operation rate more than raw bandwidth.

Step 4 - Benchmarking disk I/O

The fileio test works in three phases: prepare creates test files, run performs the I/O, and cleanup deletes the files. It uses the current directory, so first move to a directory on the disk you want to measure:

mkdir -p ~/sysbench-io
cd ~/sysbench-io

Create 8 GB of test files. If the server has more RAM than that, use --file-extra-flags=direct in the run phase (as below) so the Linux page cache does not answer reads from memory and inflate the results:

sysbench fileio --file-total-size=8G prepare
128 files, 65536Kb each, 8192Mb total
Creating files for the test...
...
8589934592 bytes written in 21.43 seconds (382.24 MiB/sec).

Random read and write (IOPS)

Random 4 KB I/O is what databases and most applications generate, and it is where storage types differ the most. Run a mixed random read/write test for 60 seconds with direct I/O and 16 threads:

sysbench fileio --file-total-size=8G --file-test-mode=rndrw \
  --file-block-size=4096 --file-extra-flags=direct \
  --threads=16 --time=60 run
File operations:
    reads/s:                      12045.31
    writes/s:                     8030.12
    fsyncs/s:                     25708.95

Throughput:
    read, MiB/s:                  47.05
    written, MiB/s:               31.37

Latency (ms):
         min:                                    0.03
         avg:                                    0.35
         max:                                   18.20
         95th percentile:                        1.16

For random tests, the numbers that matter are reads/s + writes/s (the IOPS) and the 95th percentile latency. By default sysbench calls fsync() every 100 requests, which is why fsyncs/s is high. That is realistic for databases. To measure raw device throughput without it, add --file-fsync-freq=0.

Sequential throughput

Sequential tests with large blocks measure bandwidth, which matters for backups, media and large file transfers:

sysbench fileio --file-total-size=8G --file-test-mode=seqwr \
  --file-block-size=1M --file-extra-flags=direct --time=60 run
sysbench fileio --file-total-size=8G --file-test-mode=seqrd \
  --file-block-size=1M --file-extra-flags=direct --time=60 run

Here the metric that matters is written, MiB/s or read, MiB/s.

The available modes are seqwr, seqrewr, seqrd, rndrd, rndwr and rndrw. When you are done, delete the test files:

sysbench fileio --file-total-size=8G cleanup
cd ~ && rmdir ~/sysbench-io

Step 5 - Benchmarking MySQL with OLTP workloads

sysbench ships Lua scripts that simulate an OLTP application against MySQL (or PostgreSQL). The results reflect the combined performance of CPU, memory, disk and database configuration, which makes it the most realistic of the tests. Install MySQL if it is not already present:

sudo apt install mysql-server

Create a dedicated database and user for the benchmark. Replace your_strong_password with a password of your own:

sudo mysql -e "CREATE DATABASE sbtest;
CREATE USER 'sbtest'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON sbtest.* TO 'sbtest'@'localhost';"

Load the test data: 10 tables of 100,000 rows each, around 250 MB. Use larger tables if you want the dataset to exceed the InnoDB buffer pool and exercise the disk:

sysbench oltp_read_write --db-driver=mysql \
  --mysql-user=sbtest --mysql-password=your_strong_password --mysql-db=sbtest \
  --tables=10 --table-size=100000 prepare

Run a 5-minute mixed read/write benchmark with 8 client threads, printing intermediate results every 10 seconds:

sysbench oltp_read_write --db-driver=mysql \
  --mysql-user=sbtest --mysql-password=your_strong_password --mysql-db=sbtest \
  --tables=10 --table-size=100000 \
  --threads=8 --time=300 --report-interval=10 run
[ 10s ] thds: 8 tps: 1105.63 qps: 22122.46 (r/w/o: 15487.52/4423.48/2211.46) lat (ms,95%): 11.65 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 8 tps: 1121.10 qps: 22420.03 (r/w/o: 15694.12/4483.71/2242.20) lat (ms,95%): 11.24 err/s: 0.00 reconn/s: 0.00
...
SQL statistics:
    transactions:                        335412 (1117.99 per sec.)
    queries:                             6708240 (22359.87 per sec.)

Latency (ms):
         avg:                                    7.15
         95th percentile:                       11.45

The key metrics are transactions per second (tps) and the 95th percentile latency. The per-interval lines show whether performance is stable. A tps figure that drops over time usually means the buffer pool is too small or the disk cannot keep up with writes.

Other workloads use the same options: oltp_read_only for read-heavy applications, oltp_write_only and oltp_update_index for write-heavy ones. Run the benchmark with increasing --threads values (for example 1, 8, 32 and 64) to find the concurrency where tps stops growing and latency rises.

Remove the test tables when finished:

sysbench oltp_read_write --db-driver=mysql \
  --mysql-user=sbtest --mysql-password=your_strong_password --mysql-db=sbtest \
  --tables=10 cleanup

Step 6 - Saving a baseline

A single benchmark number means little on its own. It becomes useful when you compare it with the same test on another server, or on the same server after a change. Save results with the date and the host name so you can find them later:

mkdir -p ~/benchmarks
sysbench cpu --threads=$(nproc) --time=30 run | tee ~/benchmarks/$(hostname)-cpu-$(date +%F).txt
sysbench memory --memory-block-size=1M --memory-total-size=100G --threads=$(nproc) run \
  | tee ~/benchmarks/$(hostname)-memory-$(date +%F).txt

For the disk test, prepare the files, save the run output the same way, then clean up. To extract the headline figures from saved results:

grep -H 'events per second' ~/benchmarks/*-cpu-*.txt
grep -H 'MiB/sec' ~/benchmarks/*-memory-*.txt
/home/your_user/benchmarks/web1-cpu-2026-09-25.txt:    events per second:  5921.40
/home/your_user/benchmarks/web1-cpu-2026-10-25.txt:    events per second:  5893.17

Run each test three times and use the median. Differences of a few percent between runs are normal on virtual machines; only treat larger, consistent differences as a real change.

Troubleshooting

FATAL: Cannot open file 'test_file.0' during fileio run. The test files do not exist in the current directory: you ran run from another directory, or with a different --file-num than prepare. Use identical options in all three phases and run them from the same directory.

Disk results are far higher than the storage can deliver. Reads are served from the page cache. Add --file-extra-flags=direct or make --file-total-size larger than the server's RAM.

FATAL: unable to connect to MySQL server on socket. MySQL is not running, or it uses a different socket. Check systemctl status mysql, or connect over TCP with --mysql-host=127.0.0.1.

FATAL: error 1045: Access denied for user 'sbtest'@'localhost'. The password or grants are wrong. Recreate the user with the commands in Step 5.

Conclusion

You have measured single and multi-threaded CPU speed, memory bandwidth, random and sequential disk performance, and MySQL transaction throughput with sysbench, and saved the results as a baseline. As next steps, run the same set on each new server before putting it into production, repeat the baseline after kernel or database configuration changes, and complement the storage results with network measurements between your servers using iperf3.