Benchmarking your VPS provides objective data for capacity planning, configuration validation, and provider comparison. pgbench (for PostgreSQL) and sysbench (for MySQL, CPU, memory, and disk I/O) are the standard tools for database and system benchmarking. This guide covers running meaningful benchmarks and interpreting results correctly.
sysbench Installation
# Ubuntu/Debian
sudo apt install sysbench
# RHEL/AlmaLinux
sudo dnf install sysbench
# Verify
sysbench --version
CPU Benchmarking
# Single-threaded CPU benchmark
sysbench cpu --cpu-max-prime=20000 run
# Multi-threaded (use all cores)
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) run
# Key metric: events per second (higher is better)
# Typical results:
# 1 vCPU VPS: ~800-1200 events/s
# 4 vCPU VPS: ~3200-5000 events/s
# Dedicated: ~5000-8000 events/s per core
Memory Benchmarking
# Sequential memory read/write
sysbench memory --memory-block-size=1M --memory-total-size=10G run
# Random access pattern (more realistic for databases)
sysbench memory --memory-block-size=4K --memory-total-size=10G --memory-access-mode=rnd run
# Key metrics: throughput (MiB/sec) and latency
# Good VPS: >10 GiB/s sequential, >2 GiB/s random
Disk I/O Benchmarking
# Prepare test files (16GB dataset)
sysbench fileio --file-total-size=16G prepare
# Random read/write (database-like workload)
sysbench fileio --file-total-size=16G --file-test-mode=rndrw \
--time=120 --max-requests=0 --file-extra-flags=direct \
--threads=4 run
# Sequential read (backup-like workload)
sysbench fileio --file-total-size=16G --file-test-mode=seqrd \
--time=60 --max-requests=0 --threads=1 run
# Random write (INSERT-heavy workload)
sysbench fileio --file-total-size=16G --file-test-mode=rndwr \
--time=120 --max-requests=0 --file-extra-flags=direct \
--threads=4 run
# Cleanup
sysbench fileio --file-total-size=16G cleanup
# Key metrics:
# NVMe VPS: >50,000 IOPS random read, >20,000 IOPS random write
# SSD VPS: >10,000 IOPS random read, >5,000 IOPS random write
# HDD: ~200 IOPS (avoid for databases)
MySQL Benchmarking with sysbench
# Create test database
mysql -u root -p -e "CREATE DATABASE sbtest;"
mysql -u root -p -e "GRANT ALL ON sbtest.* TO 'sbtest'@'localhost' IDENTIFIED BY 'password';"
# Prepare test data (10 tables, 1M rows each)
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-host=127.0.0.1 --mysql-user=sbtest --mysql-password=password \
--mysql-db=sbtest --tables=10 --table-size=1000000 \
prepare
# Read-heavy benchmark (80% reads, 20% writes)
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-host=127.0.0.1 --mysql-user=sbtest --mysql-password=password \
--mysql-db=sbtest --tables=10 --table-size=1000000 \
--threads=16 --time=300 --report-interval=10 \
run
# Read-only benchmark
sysbench /usr/share/sysbench/oltp_read_only.lua \
--mysql-host=127.0.0.1 --mysql-user=sbtest --mysql-password=password \
--mysql-db=sbtest --tables=10 --table-size=1000000 \
--threads=16 --time=300 \
run
# Write-only benchmark
sysbench /usr/share/sysbench/oltp_write_only.lua \
--mysql-host=127.0.0.1 --mysql-user=sbtest --mysql-password=password \
--mysql-db=sbtest --tables=10 --table-size=1000000 \
--threads=16 --time=300 \
run
# Cleanup
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-host=127.0.0.1 --mysql-user=sbtest --mysql-password=password \
--mysql-db=sbtest --tables=10 cleanup
PostgreSQL Benchmarking with pgbench
# pgbench comes with PostgreSQL
# Create test database
createdb pgbench_test
# Initialize with scale factor 50 (~750MB dataset)
pgbench -i -s 50 pgbench_test
# Simple read-write benchmark
pgbench -c 20 -j 4 -T 300 pgbench_test
# -c: concurrent clients
# -j: worker threads
# -T: duration in seconds
# Read-only benchmark
pgbench -c 20 -j 4 -T 300 -S pgbench_test
# Custom benchmark with specific query mix
cat > /tmp/custom.sql &1 | grep "events per second"
echo "Memory:"
sysbench memory --memory-block-size=4K --memory-total-size=5G run 2>&1 | grep "transferred"
echo "Disk:"
sysbench fileio --file-total-size=4G prepare > /dev/null 2>&1
sysbench fileio --file-total-size=4G --file-test-mode=rndrw --time=60 \
--file-extra-flags=direct --threads=4 run 2>&1 | grep -E "reads/s|writes/s|fsyncs/s"
sysbench fileio --file-total-size=4G cleanup > /dev/null 2>&1
echo ""
echo "Apply your tuning changes, then run again to compare."
Automated Benchmark Report
#!/bin/bash
# Generate a complete server benchmark report
REPORT="/tmp/benchmark-report-$(date +%Y%m%d).txt"
{
echo "=== Server Benchmark Report ==="
echo "Date: $(date)"
echo "Hostname: $(hostname)"
echo "CPU: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)"
echo "Cores: $(nproc)"
echo "RAM: $(free -h | awk '/Mem:/ {print $2}')"
echo "Disk: $(df -h / | awk 'NR==2 {print $2}')"
echo ""
echo "--- CPU Benchmark ---"
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) run 2>&1
echo "--- Memory Benchmark ---"
sysbench memory --memory-block-size=1M --memory-total-size=10G run 2>&1
echo "--- Disk I/O Benchmark ---"
sysbench fileio --file-total-size=4G prepare > /dev/null 2>&1
sysbench fileio --file-total-size=4G --file-test-mode=rndrw --time=60 --file-extra-flags=direct --threads=4 run 2>&1
sysbench fileio --file-total-size=4G cleanup > /dev/null 2>&1
} > "$REPORT"
echo "Report saved to $REPORT"
Summary
Benchmarking provides the objective data needed for performance tuning decisions. Use sysbench for system-level metrics (CPU, memory, disk I/O) and MySQL benchmarks, and pgbench for PostgreSQL workloads. Always benchmark before and after configuration changes to measure actual impact. Run benchmarks for at least 5 minutes to get statistically stable results, and pay attention to 95th percentile latency rather than averages — that is what your users experience during peak load.