Benchmarking de E/S de Disco con fio
fio (Flexible I/O Tester) es la herramienta estándar de la industria para benchmarking de almacenamiento que proporciona control preciso sobre características de carga de trabajo, lo que la hace esencial para validación y optimización de infraestructura de almacenamiento. Con soporte para cargas de trabajo secuenciales y aleatorias, múltiples configuraciones de trabajos y métricas de rendimiento detalladas, fio permite análisis exhaustivo de rendimiento de almacenamiento. Esta guía cubre instalación de fio, benchmarks comunes e interpretación de resultados.
Tabla de Contenidos
- Instalación de fio y Conceptos Básicos
- Pruebas de Carga de Trabajo Secuencial
- Benchmarking de E/S Aleatorio
- Análisis de IOPS y Latencia
- Archivos de Trabajos y Configuración
- Comparación de Dispositivos de Almacenamiento
- Simulación Avanzada de Cargas de Trabajo
- Análisis y Reporte de Rendimiento
- Conclusión
Instalación de fio y Conceptos Básicos
Instalación de fio
# Instalación en Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y fio
# Instalación en CentOS/RHEL
sudo yum install -y fio
# Compilar desde fuente más reciente
git clone https://github.com/axboe/fio.git
cd fio
./configure
make
sudo make install
# Verificar instalación
fio --version
Preparación de Dispositivo de Almacenamiento
# Identificar dispositivo objetivo
lsblk
sudo fdisk -l
# Verificar uso actual del dispositivo
df -h
sudo lsof | grep /dev/sda
# Para probar (solo dispositivo desmontado)
sudo fio --filename=/dev/sdb --rw=read --bs=4k --iodepth=32 \
--runtime=10 --group_reporting --name=random_read
# Para probar partición
sudo fio --filename=/mnt/test/fio_test_file --rw=read --bs=4k \
--iodepth=32 --runtime=10 --size=10G --name=file_read
Pruebas de Carga de Trabajo Secuencial
Rendimiento de Lectura Secuencial
# Lectura secuencial de línea base
fio --filename=/mnt/test/fio_test_file --rw=read --bs=1m \
--iodepth=32 --runtime=30 --name=seq_read
# Parámetros explicados:
# --filename: Ubicación del archivo de prueba
# --rw=read: Lectura secuencial
# --bs: Tamaño de bloque (1m = 1 MB)
# --iodepth: Profundidad de cola (32 típico)
# --runtime: Duración de la prueba (segundos)
# Secuencial de bloque grande (streaming)
fio --filename=/mnt/test/fio_test_file --rw=read --bs=4m \
--iodepth=16 --runtime=60 --size=100G --name=streaming_read
# Resultados típicos (SSD):
# read: IOPS=1234.56, BW=1240.56 MiB/s
# Rendimiento: ~1.2 GB/s
Rendimiento de Escritura Secuencial
# Prueba de escritura secuencial
fio --filename=/mnt/test/fio_test_file --rw=write --bs=1m \
--iodepth=32 --runtime=30 --name=seq_write --pre=touch \
--nrfiles=1 --filesize=100G
# Llenar almacenamiento con escritura secuencial (prueba de vaciado de caché)
fio --filename=/mnt/test/fio_test_file --rw=write --bs=1m \
--iodepth=64 --runtime=120 --size=500G --sync=1 --name=seq_write_sync
# Monitorear rendimiento de escritura
watch -n 1 'iostat -x -d sdb 1'
Benchmarking de E/S Aleatorio
IOPS de Lectura Aleatoria
# Medir IOPS de lectura aleatoria
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=32 --runtime=60 --size=10G --name=random_read_iops
# Resultados esperados:
# SSD: 10,000-100,000+ IOPS
# HDD: 100-200 IOPS
# Aumentar profundidad de cola para mayor potencial de IOPS
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=128 --runtime=60 --size=10G --name=high_queue_depth
# Probar con tamaño de archivo múltiple
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=64 --runtime=30 --size=100G --name=large_working_set
IOPS de Escritura Aleatoria
# Benchmark de escritura aleatoria
fio --filename=/mnt/test/fio_test_file --rw=randwrite --bs=4k \
--iodepth=32 --runtime=60 --size=10G --name=random_write_iops
# Escrituras sincronizadas (tipo diario, importante para bases de datos)
fio --filename=/mnt/test/fio_test_file --rw=randwrite --bs=4k \
--iodepth=16 --fsync=1 --runtime=60 --size=10G --name=sync_writes
# Monitorear disco durante prueba
iostat -x 1
# Probar con E/S directa (omite caché)
fio --filename=/mnt/test/fio_test_file --rw=randwrite --bs=4k \
--iodepth=32 --direct=1 --runtime=60 --size=10G --name=direct_writes
Análisis de IOPS y Latencia
Percentiles de Latencia
# Medir distribución de latencia
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=32 --runtime=60 --size=10G --lat_log=latency_results \
--name=latency_test
# Analizar percentiles de latencia
# La salida muestra: min, max, mean, p50, p95, p99, p99.9
# Resultados de latencia de ejemplo:
# lat (usec) : min=5, max=45000, avg=150, stdev=500
# percentiles (usec) :
# 50.00th=[100]
# 90.00th=[200]
# 99.00th=[500]
# 99.90th=[1500]
# 99.99th=[10000]
# Interpretar resultados:
# p99 = 99% de solicitudes se completan dentro de latencia
# p99.9 = 99.9% de solicitudes (latencia de cola)
Análisis de Distribución de Latencia
# Generar histograma de latencia detallado
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=32 --runtime=120 --size=10G --log_histogram \
--name=detailed_latency
# Probar consistencia de latencia a lo largo del tiempo
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=32 --runtime=300 --size=10G --lat_log=hourly_latency \
--name=consistency_test
# Analizar valores atípicos
# El p99.9 alto indica picos ocasionales de latencia
# Sugiere limitación térmica o eventos de recolección de basura
Archivos de Trabajos y Configuración
Crear Archivos de Trabajo de fio
# Crear archivo de trabajo reutilizable
cat > ~/storage_benchmark.fio <<'EOF'
[global]
ioengine=libaio
direct=1
group_reporting=1
time_based=1
[random_read]
rw=randread
bs=4k
iodepth=32
runtime=60
size=10G
numjobs=1
[random_write]
rw=randwrite
bs=4k
iodepth=32
runtime=60
size=10G
numjobs=1
[sequential_read]
rw=read
bs=1m
iodepth=16
runtime=60
size=100G
numjobs=1
[sequential_write]
rw=write
bs=1m
iodepth=16
runtime=60
size=100G
numjobs=1
EOF
# Ejecutar archivo de trabajo
fio ~/storage_benchmark.fio
Configuración de Múltiples Trabajos
# Crear suite de prueba completa
cat > ~/complete_benchmark.fio <<'EOF'
[global]
ioengine=libaio
direct=1
runtime=60
time_based=1
group_reporting=1
filename=/mnt/test/fio_test_file
[seq_read_4k]
rw=read
bs=4k
iodepth=32
stonewall
[seq_read_1m]
rw=read
bs=1m
iodepth=16
stonewall
[rnd_read_4k]
rw=randread
bs=4k
iodepth=32
stonewall
[rnd_write_4k]
rw=randwrite
bs=4k
iodepth=32
stonewall
[mixed_read_write]
rw=randrw
rwmixread=70
bs=4k
iodepth=32
stonewall
EOF
# Ejecutar suite completa
fio ~/complete_benchmark.fio
Comparación de Dispositivos de Almacenamiento
Pruebas de SSD vs HDD
# Prueba de rendimiento de SSD
echo "=== SSD Performance ==="
fio --filename=/mnt/ssd/fio_test --rw=randread --bs=4k \
--iodepth=32 --runtime=60 --size=10G --name=ssd_randread
# Prueba de rendimiento de HDD
echo "=== HDD Performance ==="
fio --filename=/mnt/hdd/fio_test --rw=randread --bs=4k \
--iodepth=32 --runtime=60 --size=10G --name=hdd_randread
# Comparación secuencial
echo "=== SSD Sequential ==="
fio --filename=/mnt/ssd/fio_test --rw=read --bs=1m \
--iodepth=32 --runtime=60 --size=100G --name=ssd_seq
echo "=== HDD Sequential ==="
fio --filename=/mnt/hdd/fio_test --rw=read --bs=1m \
--iodepth=32 --runtime=60 --size=100G --name=hdd_seq
Análisis de Envejecimiento y Desgaste de Unidad
# Monitorear resistencia de SSD durante pruebas
# Crear script para monitoreo de desgaste
cat > monitor_ssd_wear.sh <<'EOF'
#!/bin/bash
DEVICE=$1
echo "=== Pre-Test SSD Status ==="
sudo smartctl -a $DEVICE | grep -E "Wear_Leveling|Program_Fail|Erase_Fail"
# Ejecutar carga de trabajo sostenida
fio --filename=/mnt/test/fio_test --rw=randwrite --bs=4k \
--iodepth=32 --runtime=7200 --size=100G --name=endurance_test
echo "=== Post-Test SSD Status ==="
sudo smartctl -a $DEVICE | grep -E "Wear_Leveling|Program_Fail|Erase_Fail"
EOF
chmod +x monitor_ssd_wear.sh
./monitor_ssd_wear.sh /dev/sdb
Simulación Avanzada de Cargas de Trabajo
Simulación de Carga de Trabajo de Base de Datos
# Carga de trabajo tipo OLTP (E/S de bloque pequeño mixta)
cat > oltp_workload.fio <<'EOF'
[global]
ioengine=libaio
direct=1
group_reporting=1
runtime=300
time_based=1
[db_transactions]
rw=randrw
rwmixread=80
bs=16k
iodepth=32
numjobs=4
filename=/mnt/test/database_file
size=50G
EOF
fio oltp_workload.fio
Carga de Trabajo de Streaming/Archivo
# Carga de trabajo de streaming de video o copia de seguridad
cat > streaming_workload.fio <<'EOF'
[global]
ioengine=libaio
direct=1
group_reporting=1
[streaming_read]
rw=read
bs=4m
iodepth=8
runtime=300
numjobs=2
filename=/mnt/test/streaming_file
size=500G
EOF
fio streaming_workload.fio
Análisis y Reporte de Rendimiento
Salida JSON y Análisis
# Generar salida JSON para análisis
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=32 --runtime=60 --size=10G --output-format=json \
> results.json --name=test
# Analizar métricas específicas
cat results.json | jq '.jobs[0].read.iops'
cat results.json | jq '.jobs[0].read.bw'
cat results.json | jq '.jobs[0].read.lat_ns.percentile."99.000000"'
Crear Comparaciones de Línea Base
# Establecer línea base
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=32 --runtime=120 --size=10G --output-format=json \
> baseline.json --name=baseline
# Ejecutar después de modificaciones
fio --filename=/mnt/test/fio_test_file --rw=randread --bs=4k \
--iodepth=32 --runtime=120 --size=10G --output-format=json \
> after_tuning.json --name=tuned
# Comparar resultados
echo "Baseline IOPS: $(cat baseline.json | jq '.jobs[0].read.iops')"
echo "After tuning IOPS: $(cat after_tuning.json | jq '.jobs[0].read.iops')"
Conclusión
fio proporciona flexibilidad incomparable para validación de rendimiento de almacenamiento, permitiendo simulación precisa de cargas de trabajo del mundo real y detección de cuellos de botella de almacenamiento. Al entender efectos de tamaño de bloque, optimización de profundidad de cola e implicaciones de percentiles de latencia, los equipos de infraestructura toman decisiones informadas sobre compras de almacenamiento y optimización. El benchmarking regular establece líneas base que detectan degradación de rendimiento por edad, limitación térmica o problemas de firmware. Ya sea optimizando rendimiento de base de datos, validando nueva infraestructura de almacenamiento o solucionando cuellos de botella de E/S, fio sigue siendo la herramienta esencial para excelencia en ingeniería de almacenamiento.


