Usage

Common fio invocations, organized by what you're trying to learn.

IO engines

fio ships with many engines. The ones built into our binaries:

enginepurpose
psyncsynchronous pread/pwrite (default)
vsyncsynchronous readv/writev
pvsyncsynchronous preadv/pwritev
pvsync2preadv2/pwritev2 with flags
io_uringLinux io_uring (kernel ≥ 5.6; lowest-latency async)
mmapmmap-based file IO
nullno-op (CPU-only, useful for testing)
cpuCPU-bound workload simulation
netnetwork IO (via sendfile etc.)
execspawn external processes per IO
fileoperationsfilecreate / filestat / filedelete / etc.

Use --ioengine=NAME to switch. Optional engines (libaio, libpmem, librbd, libcurl, libibverbs, …) require external libraries — see caveats below.

Output formats

flagformatwhen
(default)human-readable plain textinteractive use
--minimalsingle semicolon-separated line per jobshell parsing
--output-format=jsonJSON documentprogrammatic parsing
--output-format=json+JSON with all per-IO samplesdeep analysis (large output)
--output-format=normal,latencyhuman + latency histogramlatency debugging
--output=FILEwrite to FILE instead of stdoutlog capture

Job files

For complex or repeated workloads, write a job file and pass it as the argument:

# bench-randwrite.fio
[global]
filename=/tmp/fio-test.bin
size=1G
bs=4k
rw=randwrite
ioengine=io_uring
runtime=60
time_based=1
group_reporting=1
numjobs=4

[job1]
stonewall
$ fio bench-randwrite.fio

Multiple sections can share [global] settings and run in parallel or sequence (stonewall = sequential).

Rate limiting & latency targets

Constrain fio to a specific throughput target to test "is my device meeting SLA" rather than "what's the max IOPS":

# 10k read IOPS, 50/90/99 latency percentiles
$ fio --rw=randread --bs=4k --size=10G --filename=/dev/nvme0n1 \
      --rate_iops=10000 \
      --percentile_list=50:90:99:99.9:99.99 \
      --output-format=normal,latency

Caveats