fio recipes for shared-FS benchmarks
Generate ready-to-run fio commands tuned for an NFS-style or DPU-fronted parallel filesystem.
These are the eight runs we usually fire off when validating a freshly mounted shared filesystem (Weka, VAST, Lustre). Together they give a reasonable picture of throughput, IOPS, and tail latency without taking all afternoon — each runs for 60 seconds.
Always do the setup run first so the file exists at full size; otherwise the seq-read jobs spend most of their time waiting on writes to allocate.
setupPre-create test file (64 GB)one-shot
fio --name=create --rw=write --bs=1m --size=64g \ --numjobs=1 --end_fsync=1 \ --filename=/mnt/shared/fio-testfile
Run once before the read tests. NFS clients hate writing into a sparse file mid-benchmark.
seqSequential read · 1M block8 jobs · iodepth 32
fio --name=seq-1m --ioengine=libaio --direct=1 \ --rw=read --bs=1m --numjobs=8 --iodepth=32 \ --size=64g --runtime=60 --time_based --group_reporting \ --filename=/mnt/shared/fio-testfile
Throughput-oriented. Expect bandwidth close to NIC line rate on a healthy mount.
seqSequential read · 256K block8 jobs · iodepth 32
fio --name=seq-256k --ioengine=libaio --direct=1 \ --rw=read --bs=256k --numjobs=8 --iodepth=32 \ --size=64g --runtime=60 --time_based --group_reporting \ --filename=/mnt/shared/fio-testfile
randRandom read · 4K · deep queue8 jobs · iodepth 64
fio --name=rand-4k-deep --ioengine=libaio --direct=1 \ --rw=randread --bs=4k --numjobs=8 --iodepth=64 \ --size=64g --runtime=60 --time_based --group_reporting \ --filename=/mnt/shared/fio-testfile
IOPS test. Useful for "small-file inference" workloads.
randRandom read · 4K · shallow queue4 jobs · iodepth 4
fio --name=rand-4k-shallow --ioengine=libaio --direct=1 \ --rw=randread --bs=4k --numjobs=4 --iodepth=4 \ --size=64g --runtime=60 --time_based --group_reporting \ --filename=/mnt/shared/fio-testfile
latLatency probe · iodepth 1p99 / p99.9
fio --name=lat-serial --ioengine=libaio --direct=1 \ --rw=randread --bs=4k --numjobs=1 --iodepth=1 \ --size=64g --runtime=60 --time_based --group_reporting --lat_percentiles=1 \ --filename=/mnt/shared/fio-testfile
Single in-flight IO. The p99 / p99.9 numbers tell you about tail latency under no contention.
mixMixed 70 % read / 30 % write8 jobs · 256K
fio --name=mix-70r --ioengine=libaio --direct=1 \ --rw=randrw --bs=256k --numjobs=8 --iodepth=16 \ --size=64g --runtime=60 --time_based --group_reporting --rwmixread=70 --lat_percentiles=1 \ --filename=/mnt/shared/fio-testfile
mixMixed 90 % read / 10 % write16 jobs · 64K
fio --name=mix-90r --ioengine=libaio --direct=1 \ --rw=randrw --bs=64k --numjobs=16 --iodepth=16 \ --size=64g --runtime=60 --time_based --group_reporting --rwmixread=90 --lat_percentiles=1 \ --filename=/mnt/shared/fio-testfile
What to look for in the output
- BW=… — aggregate bandwidth. For a 100GbE-fronted pool on a single client, the seq-1m run should comfortably exceed 5 GB/s.
- IOPS=… — aggregate IOPS. The rand-4k-deep run is the one that stresses metadata + small-IO paths.
- clat percentiles — latency distribution. p99.9 in the single milliseconds is good; tens of milliseconds means the storage tier or the network is queuing.
- On NFSv3 mounts you almost always need
--ioengine=libaioand--direct=1to stop the kernel from caching everything in page cache.