fio (Flexible I/O Tester) ist das Standard-Tool für Storage-Benchmarks unter Linux. Es simuliert verschiedene I/O-Workloads und misst Durchsatz, IOPS und Latenz.

Installation

# Debian/Ubuntu
apt install fio

# RHEL/CentOS
dnf install fio

# Version prüfen
fio --version

Grundlagen

Einfacher Test

# Sequenzielles Schreiben
fio --name=seqwrite --rw=write --bs=1M --size=1G --numjobs=1 --runtime=60

# Sequenzielles Lesen
fio --name=seqread --rw=read --bs=1M --size=1G --numjobs=1 --runtime=60

# Random Read
fio --name=randread --rw=randread --bs=4K --size=1G --numjobs=1 --runtime=60

# Random Write
fio --name=randwrite --rw=randwrite --bs=4K --size=1G --numjobs=1 --runtime=60

Wichtige Parameter

| Parameter | Beschreibung | |-----------|--------------| | --name | Test-Name | | --rw | I/O-Pattern (read, write, randread, randwrite, randrw) | | --bs | Block-Größe | | --size | Testdatei-Größe | | --numjobs | Parallele Prozesse | | --runtime | Laufzeit in Sekunden | | --iodepth | I/O Queue Depth | | --direct | Direct I/O (bypasses Cache) |

I/O-Pattern

Sequenziell

# Sequenzielles Schreiben (große Dateien)
fio --name=seqwrite --rw=write --bs=1M --size=4G --direct=1 --runtime=60

# Sequenzielles Lesen
fio --name=seqread --rw=read --bs=1M --size=4G --direct=1 --runtime=60

Random (zufällig)

# Random Read (4K Blöcke, typisch für Datenbanken)
fio --name=randread --rw=randread --bs=4K --size=1G --direct=1 --numjobs=4 --iodepth=32 --runtime=60

# Random Write
fio --name=randwrite --rw=randwrite --bs=4K --size=1G --direct=1 --numjobs=4 --iodepth=32 --runtime=60

Mixed (gemischt)

# 70% Read, 30% Write
fio --name=randrw --rw=randrw --rwmixread=70 --bs=4K --size=1G --direct=1 --numjobs=4 --iodepth=32 --runtime=60

I/O-Engines

# Linux AIO (asynchron)
fio --name=test --rw=randread --ioengine=libaio --bs=4K --direct=1 --iodepth=32

# Sync (synchron)
fio --name=test --rw=randread --ioengine=sync --bs=4K --direct=1

# io_uring (modern, schnell)
fio --name=test --rw=randread --ioengine=io_uring --bs=4K --direct=1 --iodepth=32

Job-Dateien

Beispiel-Jobfile

# benchmark.fio
[global]
ioengine=libaio
direct=1
size=1G
runtime=60
time_based

[seq-read]
rw=read
bs=1M
numjobs=1

[seq-write]
rw=write
bs=1M
numjobs=1

[rand-read-4k]
rw=randread
bs=4K
numjobs=4
iodepth=32

[rand-write-4k]
rw=randwrite
bs=4K
numjobs=4
iodepth=32

[rand-rw-4k]
rw=randrw
rwmixread=70
bs=4K
numjobs=4
iodepth=32
fio benchmark.fio

Spezifische Tests

SSD IOPS-Test

# Maximale 4K Random Read IOPS
fio --name=max-iops \
    --rw=randread \
    --bs=4K \
    --size=4G \
    --numjobs=4 \
    --iodepth=256 \
    --ioengine=libaio \
    --direct=1 \
    --runtime=60 \
    --group_reporting

Latenz-Test

# Minimale Latenz (1 Job, niedriger iodepth)
fio --name=latency \
    --rw=randread \
    --bs=4K \
    --size=1G \
    --numjobs=1 \
    --iodepth=1 \
    --ioengine=libaio \
    --direct=1 \
    --runtime=60 \
    --lat_percentiles=1

Durchsatz-Test

# Maximaler sequenzieller Durchsatz
fio --name=throughput \
    --rw=read \
    --bs=1M \
    --size=4G \
    --numjobs=4 \
    --iodepth=32 \
    --ioengine=libaio \
    --direct=1 \
    --runtime=60 \
    --group_reporting

Datenbank-Workload

# Simuliert Datenbank-ähnliche I/O
fio --name=db-workload \
    --rw=randrw \
    --rwmixread=80 \
    --bs=8K \
    --size=4G \
    --numjobs=8 \
    --iodepth=64 \
    --ioengine=libaio \
    --direct=1 \
    --runtime=120 \
    --group_reporting

Ausgabe verstehen

Wichtige Metriken

read: IOPS=95.3k, BW=372MiB/s (390MB/s)(22.3GiB/60001msec)
     slat (nsec): min=1230, max=123456, avg=2100.00, stdev=890.00
     clat (usec): min=54, max=15234, avg=335.00, stdev=120.00
      lat (usec): min=56, max=15237, avg=337.00, stdev=121.00
    clat percentiles (usec):
     |  1.00th=[  145],  5.00th=[  180], 10.00th=[  200],
     | 20.00th=[  235], 30.00th=[  260], 40.00th=[  285],
     | 50.00th=[  310], 60.00th=[  338], 70.00th=[  371],
     | 80.00th=[  416], 90.00th=[  490], 95.00th=[  570],
     | 99.00th=[  750], 99.50th=[  848], 99.90th=[ 1090],
     | 99.95th=[ 1237], 99.99th=[ 2245]

| Metrik | Bedeutung | |--------|-----------| | IOPS | I/O Operationen pro Sekunde | | BW | Bandbreite (Durchsatz) | | slat | Submission Latency | | clat | Completion Latency | | lat | Gesamtlatenz |

JSON-Ausgabe

# JSON-Ausgabe
fio benchmark.fio --output-format=json --output=results.json

# JSON + Human-readable
fio benchmark.fio --output-format=json+ --output=results.json

Direkter Gerätezugriff

# ACHTUNG: Zerstört alle Daten!
# Auf raw Device (ohne Dateisystem)
fio --name=rawtest \
    --rw=randread \
    --bs=4K \
    --filename=/dev/nvme0n1 \
    --numjobs=4 \
    --iodepth=32 \
    --ioengine=libaio \
    --direct=1 \
    --runtime=60 \
    --group_reporting

Vergleichs-Script

#!/bin/bash
# storage-benchmark.sh

TARGET=${1:-/mnt/testdisk}
RESULTS="fio-results-$(date +%Y%m%d-%H%M%S)"

mkdir -p $RESULTS

echo "Running benchmarks on $TARGET..."

# Sequenziell
fio --name=seq-read --rw=read --bs=1M --size=1G --directory=$TARGET \
    --direct=1 --runtime=60 --output-format=json \
    --output=$RESULTS/seq-read.json

fio --name=seq-write --rw=write --bs=1M --size=1G --directory=$TARGET \
    --direct=1 --runtime=60 --output-format=json \
    --output=$RESULTS/seq-write.json

# Random 4K
fio --name=rand-read-4k --rw=randread --bs=4K --size=1G --directory=$TARGET \
    --numjobs=4 --iodepth=32 --ioengine=libaio --direct=1 --runtime=60 \
    --output-format=json --output=$RESULTS/rand-read-4k.json

fio --name=rand-write-4k --rw=randwrite --bs=4K --size=1G --directory=$TARGET \
    --numjobs=4 --iodepth=32 --ioengine=libaio --direct=1 --runtime=60 \
    --output-format=json --output=$RESULTS/rand-write-4k.json

echo "Results saved to $RESULTS/"

Zusammenfassung

| Test-Typ | Typische Verwendung | |----------|---------------------| | Seq Read/Write | Große Dateitransfers | | Random 4K | Datenbanken, VMs | | Mixed R/W | Realistische Workloads |

| Parameter | Empfehlung | |-----------|------------| | direct=1 | Für echte Storage-Messung | | iodepth | Hoch für NVMe, niedrig für HDD | | numjobs | 1-4 für Latenz, mehr für Durchsatz | | runtime | Mindestens 60s für stabile Werte |

| Engine | Verwendung | |--------|------------| | libaio | Linux Standard | | io_uring | Modern, sehr schnell | | sync | Einfache Tests |

Fazit

fio ist unverzichtbar für Storage-Performance-Tests. Direct I/O misst echte Hardware-Performance. Job-Dateien ermöglichen reproduzierbare Tests. Die Ausgabe liefert detaillierte Latenz-Percentile. Für aussagekräftige Ergebnisse sollten Tests mehrfach durchgeführt werden.