Snippets

How to Benchmark Disk I/O Speed on Linux VPS, VMs and Containers with dd and fio

The reason I put these benchmarking notes together was troubleshooting a persistent storage headache with my friend Jim. Jim was constantly running into sluggish performance and high I/O wait on his Proxmox server across various LXC containers and KVM virtual machines. Whenever a background cron job ran or MySQL attempted basic writes, the entire container stack would grind to a halt.

Before tweaking ZFS pool settings, disk schedulers, or cache modes, our first step was getting solid baseline data inside the containers and host nodes to see what was actually happening under the hood.

Whether you’re diagnosing a Proxmox container, setting up a fresh KVM virtual machine, or testing a new cloud VPS, checking your real storage throughput is essential. However, simple test commands often produce wildly inaccurate results if you don’t account for memory caching.

A lot of people test write speeds by running a quick dd command:

# Don't rely on this standard command:
dd if=/dev/zero of=testfile bs=1G count=1

If you run that inside a virtual machine or container, you will often see crazy speeds like 2.4 GB/s on basic spinning rust or cheap shared hosting. What you’re actually measuring is the host kernel’s RAM page cache buffering the write in memory, not the physical storage committing the blocks.

The Real Direct Write Test with dd

To bypass the operating system’s write buffer cache and measure real direct-to-disk write throughput, use the oflag=dsync parameter:

dd if=/dev/zero of=testfile bs=64k count=16k oflag=dsync

This writes a 1GB file in 64KB blocks and forces synchronized I/O for data and metadata on every block.

  • Typical HDD (7.2k / 10k RPM): 30 – 70 MB/s
  • Standard SATA SSD: 180 – 450 MB/s
  • Enterprise NVMe / Fast Array: 600+ MB/s

Once the test finishes, clean up the test file:

rm -f testfile

Measuring 4K Random Read/Write IOPS with fio

Sequential throughput is only half the story. Most web servers, MySQL databases, and control panels deal with thousands of tiny 4KB random reads and writes.

If you have fio (Flexible I/O Tester) installed (apt-get install fio or yum install fio), run this quick 4K random read/write benchmark:

fio --name=random-rw --ioengine=libaio --rw=randrw --rwmixread=75 --bs=4k --direct=1 --size=512m --numjobs=1 --runtime=30 --group_reporting

This tests a 75% read / 25% write workload with direct I/O. Look at the IOPS output at the end:

  • Under 500 IOPS: Overloaded or slow spinning rust. Your MySQL queries will choke under traffic.
  • 2,000 – 10,000 IOPS: Decent shared SSD VPS performance.
  • 25,000+ IOPS: Solid enterprise NVMe tier.

Storage performance tiers comparison
Storage performance tiers comparison: throughput and IOPS ratings for HDDs, SATA SSDs, and NVMe drives

A quick 60-second test before migrating production databases or clients will save you hours of troubleshooting later on. If you’re managing Proxmox hosts, check out my first setup guide for Proxmox servers for repository and storage tuning steps.