Zum Inhalt springen

fio

fio (Flexible I/O Tester) ist das Industriestandard-Tool zum Benchmarking und Stress-Testing von Speicher-Subsystemen. Es unterstützt konfigurierbare I/O-Muster, mehrere Engines (libaio, io_uring, sync), Job-Dateien und detaillierte Latenz-/Durchsatz-Berichte.

Installation

# Ubuntu/Debian
sudo apt-get install fio

# RHEL/CentOS/Fedora
sudo dnf install fio

# macOS
brew install fio

# From source
git clone https://github.com/axboe/fio.git
cd fio
./configure
make -j$(nproc)
sudo make install

# Verify
fio --version

Random Read/Write

4K Random Read (Common SSD Test)

# 4K random read - IOPS test
fio --name=randread \
    --ioengine=libaio \
    --iodepth=32 \
    --rw=randread \
    --bs=4k \
    --direct=1 \
    --size=1G \
    --numjobs=4 \
    --runtime=60 \
    --time_based \
    --group_reporting \
    --filename=/tmp/fio-test

4K Random Write

# 4K random write - IOPS test
fio --name=randwrite \
    --ioengine=libaio \
    --iodepth=32 \
    --rw=randwrite \
    --bs=4k \
    --direct=1 \
    --size=1G \
    --numjobs=4 \
    --runtime=60 \
    --time_based \
    --group_reporting \
    --filename=/tmp/fio-test

Mixed Random Read/Write

# 70/30 read/write mix (typical database workload)
fio --name=randrw \
    --ioengine=libaio \
    --iodepth=32 \
    --rw=randrw \
    --rwmixread=70 \
    --bs=4k \
    --direct=1 \
    --size=1G \
    --numjobs=4 \
    --runtime=60 \
    --time_based \
    --group_reporting \
    --filename=/tmp/fio-test

Sequential I/O

Sequential Read (Throughput)

# Sequential read - bandwidth test
fio --name=seqread \
    --ioengine=libaio \
    --iodepth=16 \
    --rw=read \
    --bs=1M \
    --direct=1 \
    --size=4G \
    --numjobs=1 \
    --runtime=60 \
    --time_based \
    --group_reporting \
    --filename=/tmp/fio-test

Sequential Write

# Sequential write - bandwidth test
fio --name=seqwrite \
    --ioengine=libaio \
    --iodepth=16 \
    --rw=write \
    --bs=1M \
    --direct=1 \
    --size=4G \
    --numjobs=1 \
    --runtime=60 \
    --time_based \
    --group_reporting \
    --filename=/tmp/fio-test

Job Files

Basic Job File

; storage-bench.fio
[global]
ioengine=libaio
iodepth=32
direct=1
size=1G
runtime=60
time_based
group_reporting
filename=/tmp/fio-test

[4k-randread]
rw=randread
bs=4k
numjobs=4

[4k-randwrite]
rw=randwrite
bs=4k
numjobs=4
stonewall

[1m-seqread]
rw=read
bs=1M
numjobs=1
stonewall

[1m-seqwrite]
rw=write
bs=1M
numjobs=1
stonewall
# Run the job file
fio storage-bench.fio

Database Simulation Job

; database.fio - Simulates database I/O patterns
[global]
ioengine=libaio
direct=1
time_based
runtime=120
filename=/tmp/fio-db-test

[db-data-read]
rw=randread
bs=8k
iodepth=64
numjobs=8
size=4G

[db-log-write]
rw=write
bs=4k
iodepth=1
numjobs=1
size=512M
fsync=1

I/O Engines

# libaio - Linux native async I/O (most common for benchmarks)
fio --ioengine=libaio --iodepth=32 --rw=randread --bs=4k \
    --direct=1 --size=1G --filename=/tmp/fio-test --name=test

# io_uring - Modern Linux I/O (kernel 5.1+, fastest)
fio --ioengine=io_uring --iodepth=128 --rw=randread --bs=4k \
    --direct=1 --size=1G --filename=/tmp/fio-test --name=test

# sync - Synchronous I/O (simple, single-threaded baseline)
fio --ioengine=sync --rw=randread --bs=4k \
    --direct=1 --size=1G --filename=/tmp/fio-test --name=test

# psync - POSIX sync (pread/pwrite, allows seeking)
fio --ioengine=psync --rw=randread --bs=4k \
    --direct=1 --size=1G --filename=/tmp/fio-test --name=test

# mmap - Memory-mapped I/O
fio --ioengine=mmap --rw=randread --bs=4k \
    --size=1G --filename=/tmp/fio-test --name=test

# List all available engines
fio --enghelp

Output Parsing

JSON Output

# Get JSON output for scripting
fio --name=test --ioengine=libaio --rw=randread --bs=4k \
    --direct=1 --size=256M --iodepth=32 --output-format=json \
    --filename=/tmp/fio-test > results.json

# Parse key metrics
python3 -c "
import json
with open('results.json') as f:
    data = json.load(f)
job = data['jobs'][0]
read = job['read']
print(f'IOPS: {read[\"iops\"]:.0f}')
print(f'BW: {read[\"bw\"] / 1024:.1f} MB/s')
print(f'Lat avg: {read[\"lat_ns\"][\"mean\"] / 1000:.1f} us')
print(f'Lat p99: {read[\"clat_ns\"][\"percentile\"][\"99.000000\"] / 1000:.1f} us')
"

Terse Output

# Terse (semicolon-separated) output for scripting
fio --name=test --ioengine=libaio --rw=randread --bs=4k \
    --direct=1 --size=256M --iodepth=32 --output-format=terse \
    --filename=/tmp/fio-test

Profiles and Common Test Patterns

NVMe SSD Full Test

# Comprehensive NVMe SSD benchmark
# WARNING: Use a test file, not a raw device, unless you know what you're doing

# 1. Sequential read throughput
fio --name=seq-read --ioengine=io_uring --iodepth=64 --rw=read \
    --bs=128k --direct=1 --size=4G --numjobs=4 --runtime=60 \
    --time_based --group_reporting --filename=/tmp/fio-test

# 2. Sequential write throughput
fio --name=seq-write --ioengine=io_uring --iodepth=64 --rw=write \
    --bs=128k --direct=1 --size=4G --numjobs=4 --runtime=60 \
    --time_based --group_reporting --filename=/tmp/fio-test

# 3. Random 4K read IOPS
fio --name=rand-read --ioengine=io_uring --iodepth=256 --rw=randread \
    --bs=4k --direct=1 --size=4G --numjobs=4 --runtime=60 \
    --time_based --group_reporting --filename=/tmp/fio-test

# 4. Random 4K write IOPS
fio --name=rand-write --ioengine=io_uring --iodepth=256 --rw=randwrite \
    --bs=4k --direct=1 --size=4G --numjobs=4 --runtime=60 \
    --time_based --group_reporting --filename=/tmp/fio-test

Latency-Sensitive Test

# Measure latency at low queue depth (realistic for single-user apps)
fio --name=latency \
    --ioengine=libaio \
    --iodepth=1 \
    --rw=randread \
    --bs=4k \
    --direct=1 \
    --size=1G \
    --numjobs=1 \
    --runtime=60 \
    --time_based \
    --percentile_list=50:90:95:99:99.9:99.99 \
    --filename=/tmp/fio-test

fio Plot

# Generate bandwidth/IOPS log for plotting
fio --name=test --ioengine=libaio --rw=randread --bs=4k \
    --direct=1 --size=1G --iodepth=32 --runtime=60 --time_based \
    --write_bw_log=results --write_iops_log=results --write_lat_log=results \
    --log_avg_msec=1000 --filename=/tmp/fio-test

# Plot with fio_generate_plots (requires gnuplot)
sudo apt-get install gnuplot
fio_generate_plots results

# Log files generated:
# results_bw.log    - Bandwidth over time
# results_iops.log  - IOPS over time
# results_lat.log   - Latency over time

Tipps

# Always use --direct=1 to bypass OS page cache
# Always use --time_based with --runtime for consistent results
# Use --group_reporting to aggregate stats across jobs
# Run tests multiple times for reliable numbers
# Pre-condition SSDs with a full write before benchmarking

# Clean up test files
rm -f /tmp/fio-test