fio and dd are your go-to tools for understanding storage performance, but they measure fundamentally different things.

Let’s see fio in action. Imagine you have a raw block device, say /dev/nvme0n1p1, and you want to test its sequential read performance. You’d craft a job file like this:

[global]
ioengine=libaio
direct=1
bs=1M
numjobs=4
iodepth=32
size=10G
rw=read
filename=/dev/nvme0n1p1

[sequential-read]
description="Sequential Read Test"

Then, you’d run it with fio --name=sequential-read --filename=/dev/nvme0n1p1 --bs=1M --size=10G --rw=read --ioengine=libaio --numjobs=4 --iodepth=32 --direct=1.

The output will be dense, but crucial:

sequential-read: (g=0): rw=read, bs=(1M)
...
fio-job-1: (g=0): pid=12345, этапы=1
fio-job-1: (g=0): Sequential Read
fio-job-1: (g=0): io_u depth 32, iodepth 32
fio-job-1: (g=0): Size 10GiB, bw=3000MB/s, iops=3000, runt=3410msec
...

This tells you that with 4 parallel jobs, each issuing 32 I/O operations of 1MB at a time, to a total of 10GB, your storage delivered 3000 Megabytes per second. This is fio’s specialty: simulating application-like workloads by controlling concurrency, block size, read/write mix, and I/O depth. It’s about how your storage behaves when multiple processes or threads are hammering it simultaneously. The ioengine (libaio here) determines how fio interfaces with the kernel, and direct=1 bypasses the operating system’s page cache, ensuring you’re measuring the raw device performance.

Now, consider dd. It’s a much simpler tool, primarily for data copying and low-level block manipulation. To do a similar sequential read test with dd, you might run:

dd if=/dev/nvme0n1p1 of=/dev/null bs=1M count=10240 status=progress

This command reads 10GB (10240 blocks of 1MB) from /dev/nvme0n1p1 and discards it by writing to /dev/null. The status=progress will show you the throughput in real-time. You’ll get a single throughput number, like "2500MB/s".

The key difference is that dd typically operates with a single thread of execution and a default buffer size (though bs can change this). It doesn’t inherently simulate the complex, multi-threaded, and often random I/O patterns that real applications generate. dd is great for a quick sanity check of raw sequential throughput, but it’s a blunt instrument compared to fio’s surgical precision for workload simulation.

The problem fio solves is the gap between synthetic benchmarks and real-world application performance. Storage systems are complex, with layers of caching, parallel processing capabilities, and intricate scheduling algorithms. A simple dd test might show high sequential throughput, but it won’t reveal how the drive handles the random 4KB reads that a database might perform, or the mixed read/write patterns of a web server. fio allows you to define these patterns, isolate variables, and get a much more accurate picture of how your storage will perform under specific application loads. You can tune bs (block size), rw (read/write mix, e.g., randread, randwrite, readwrite), iodepth (how many I/O requests are outstanding per job), and numjobs (how many parallel jobs) to mimic virtually any workload.

The mental model for fio is a "workload generator." You tell it what kind of work to do (read, write, mixed, random, sequential, specific block sizes, specific concurrency levels) and where to do it (the filename). It then orchestrates the execution of that work, reporting back on the performance achieved. dd, on the other hand, is a "data mover." Its primary function is to copy data, and performance is a secondary measurement of that copying activity.

One thing that trips people up is the direct parameter in fio. When direct=0 (the default), fio uses the operating system’s page cache. This means that subsequent runs of the same test might show significantly higher performance as the data is served from RAM instead of the physical storage device. Setting direct=1 bypasses the page cache, forcing fio to interact directly with the storage device, providing a more accurate measure of the device’s intrinsic performance characteristics, rather than the combined performance of the device and the OS cache.

Once you’ve mastered fio and dd, you’ll want to explore tools like iometer or cloud provider-specific performance testing utilities.

Want structured learning?

Take the full Storage Systems course →