fio (Flexible I/O Tester) es la herramienta de referencia para medir el rendimiento de almacenamiento en Linux. Permite definir con precisión el patrón de acceso (aleatorio o secuencial), el tamaño de bloque, la profundidad de cola y el número de procesos, y devuelve IOPS, ancho de banda y percentiles de latencia. En este tutorial instalarás fio en Ubuntu 24.04, medirás IOPS aleatorias y rendimiento secuencial, evaluarás la latencia de fsync que sufren las bases de datos y guardarás las pruebas en un archivo de trabajo reutilizable.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Al menos 5 GB libres en el sistema de archivos que quieras medir.
Advertenciatodas las pruebas de esta guía escriben en un archivo dentro de un sistema de archivos montado. Nunca apuntes una prueba de escritura de fio a un dispositivo de bloque (por ejemplo
/dev/sdao/dev/vdb) que contenga datos: los sobrescribirás.
Paso 1: Instalar fio
fio está en los repositorios oficiales de Ubuntu:
sudo apt update
sudo apt install fio
Comprueba la versión:
fio --version
fio-3.36
Identifica en qué disco y sistema de archivos está el directorio donde harás las pruebas:
lsblk
df -h ~
Crea un directorio de trabajo en ese sistema de archivos:
mkdir ~/fio-test
Paso 2: Entender los parámetros clave
Todas las pruebas de esta guía combinan los mismos parámetros. Conviene entenderlos antes de lanzar nada:
| Parámetro | Qué controla | Valores habituales |
|---|---|---|
--rw | Patrón de acceso | randread, randwrite, randrw, read, write |
--bs | Tamaño de bloque por operación | 4k para IOPS, 1M para ancho de banda |
--iodepth | Operaciones en vuelo por proceso | 1 para latencia, 32-64 para máximo rendimiento |
--numjobs | Procesos en paralelo | 1-4 |
--ioengine | Cómo se envían las operaciones | libaio (asíncrono), sync |
--direct=1 | Salta la caché de páginas del kernel | Siempre, salvo que quieras medir la caché |
--size | Tamaño del archivo de prueba | 4G o más |
--runtime y --time_based | Duración fija de la prueba | 60 segundos |
Sin --direct=1, las lecturas pueden servirse desde la RAM y obtendrás cifras irreales.
Paso 3: Medir IOPS de lectura aleatoria
Las lecturas aleatorias de 4 KB son el patrón más exigente para un disco y el que más se parece a una base de datos o a muchos usuarios leyendo archivos pequeños a la vez:
fio --name=randread --directory=$HOME/fio-test --size=4G \
--rw=randread --bs=4k --iodepth=64 --numjobs=1 \
--ioengine=libaio --direct=1 --runtime=60 --time_based --group_reporting
La primera vez, fio crea el archivo de 4 GB (Laying out IO file), lo que tarda unos segundos. Al terminar verás un bloque como este:
randread: (groupid=0, jobs=1): err= 0: pid=4121: Thu Sep 25 10:12:44 2026
read: IOPS=48.2k, BW=188MiB/s (197MB/s)(11.0GiB/60001msec)
slat (usec): min=2, max=412, avg= 4.18, stdev= 2.07
clat (usec): min=112, max=9870, avg=1322.40, stdev=301.55
lat (usec): min=118, max=9874, avg=1326.71, stdev=301.60
clat percentiles (usec):
| 1.00th=[ 783], 5.00th=[ 914], 10.00th=[ 996], 20.00th=[ 1106],
| 30.00th=[ 1172], 40.00th=[ 1237], 50.00th=[ 1303], 60.00th=[ 1369],
| 70.00th=[ 1434], 80.00th=[ 1532], 90.00th=[ 1680], 95.00th=[ 1811],
| 99.00th=[ 2212], 99.50th=[ 2442], 99.90th=[ 3261], 99.95th=[ 3818],
| 99.99th=[ 6128]
Cómo leerlo:
- IOPS: operaciones por segundo. Es la cifra principal en pruebas de 4 KB.
- BW: ancho de banda. En bloques pequeños es simplemente IOPS multiplicado por 4 KB.
- clat: latencia de finalización de cada operación.
slates el tiempo de envío ylatla suma de ambos. - Percentiles:
99.00th=[ 2212]significa que el 99 % de las lecturas tardó 2,2 ms o menos. Los percentiles altos (99,9 % y 99,99 %) muestran los picos que notan las aplicaciones.
Como referencia orientativa, un disco mecánico da del orden de 100-200 IOPS aleatorias, un SSD SATA decenas de miles y un NVMe cientos de miles. En un VPS, el resultado suele estar marcado por los límites de IOPS del plan y no solo por el hardware.
Paso 4: Medir IOPS de escritura aleatoria y cargas mixtas
La escritura aleatoria usa la misma sintaxis cambiando --rw:
fio --name=randwrite --directory=$HOME/fio-test --size=4G \
--rw=randwrite --bs=4k --iodepth=64 --numjobs=1 \
--ioengine=libaio --direct=1 --runtime=60 --time_based --group_reporting
La mayoría de aplicaciones reales mezclan lecturas y escrituras. Esta prueba reparte un 70 % de lecturas y un 30 % de escrituras:
fio --name=randrw --directory=$HOME/fio-test --size=4G \
--rw=randrw --rwmixread=70 --bs=4k --iodepth=64 --numjobs=1 \
--ioengine=libaio --direct=1 --runtime=60 --time_based --group_reporting
La salida incluye una línea read: y otra write: con sus propias IOPS y latencias.
Paso 5: Medir el rendimiento secuencial
Copias de seguridad, vídeo o importaciones masivas trabajan con bloques grandes en orden. Para medir el ancho de banda máximo usa bloques de 1 MB:
fio --name=seqread --directory=$HOME/fio-test --size=4G \
--rw=read --bs=1M --iodepth=16 --numjobs=1 \
--ioengine=libaio --direct=1 --runtime=60 --time_based --group_reporting
read: IOPS=1742, BW=1742MiB/s (1827MB/s)(102GiB/60003msec)
En pruebas secuenciales la cifra relevante es BW. Para escritura secuencial, cambia --rw=read por --rw=write.
Paso 6: Medir la latencia de fsync para bases de datos
Las bases de datos y sistemas como etcd confirman cada transacción con fsync o fdatasync, y esperan a que el disco confirme que los datos son persistentes. Esa latencia importa más que las IOPS máximas. Esta prueba escribe bloques pequeños y fuerza fdatasync tras cada escritura, con un único proceso y sin cola:
fio --name=fsync-test --directory=$HOME/fio-test --size=256M \
--rw=write --bs=4k --ioengine=sync --fdatasync=1 --runtime=60 --time_based
Busca en la salida la sección de sincronización:
fsync/fdatasync/sync_file_range:
sync (usec): min=210, max=8412, avg=402.18, stdev=190.33
sync percentiles (usec):
| 1.00th=[ 245], 5.00th=[ 265], 10.00th=[ 277], 20.00th=[ 302],
| 50.00th=[ 359], 90.00th=[ 562], 95.00th=[ 652], 99.00th=[ 1057],
| 99.90th=[ 2966], 99.95th=[ 3884], 99.99th=[ 7046]
Un percentil 99 por debajo de 10 ms es el mínimo que se suele recomendar para etcd. Valores de pocos cientos de microsegundos son típicos de un NVMe local.
Paso 7: Crear un archivo de trabajo reutilizable
En lugar de repetir parámetros en la línea de órdenes, fio acepta archivos de trabajo en formato INI. La sección [global] define los valores comunes y cada sección siguiente es una prueba. stonewall hace que cada prueba espere a que termine la anterior, para que no se ejecuten a la vez.
Crea el archivo:
nano ~/disk-benchmark.fio
Añade este contenido:
[global]
directory=${HOME}/fio-test
size=4G
ioengine=libaio
direct=1
runtime=60
time_based
group_reporting
[rand-read-4k]
rw=randread
bs=4k
iodepth=64
stonewall
[rand-write-4k]
rw=randwrite
bs=4k
iodepth=64
stonewall
[mixed-70-30-4k]
rw=randrw
rwmixread=70
bs=4k
iodepth=64
stonewall
[seq-read-1m]
rw=read
bs=1M
iodepth=16
stonewall
[seq-write-1m]
rw=write
bs=1M
iodepth=16
stonewall
fio expande variables de entorno con la sintaxis ${VAR}, por eso ${HOME} apunta a tu directorio personal. Ejecuta el conjunto completo, que tarda unos 5 minutos:
fio ~/disk-benchmark.fio
Cada prueba aparece con su nombre en la salida, seguida de su bloque de IOPS, ancho de banda y latencia.
Paso 8: Guardar los resultados en JSON
Para comparar ejecuciones, por ejemplo antes y después de cambiar de plan o de sistema de archivos, guarda la salida en JSON:
fio --output-format=json --output=$HOME/fio-$(date +%F).json ~/disk-benchmark.fio
Instala jq y extrae las IOPS de lectura y el percentil 99 de latencia (en microsegundos) de cada prueba:
sudo apt install jq
jq -r '.jobs[] | [.jobname, (.read.iops|floor), (.write.iops|floor), ((.read.clat_ns.percentile["99.000000"] // 0)/1000|floor)] | @tsv' ~/fio-$(date +%F).json
rand-read-4k 48213 0 2212
rand-write-4k 0 31877 0
mixed-70-30-4k 25110 10762 3032
seq-read-1m 1742 0 9765
seq-write-1m 0 1508 0
Las columnas son: nombre de la prueba, IOPS de lectura, IOPS de escritura y percentil 99 de lectura en microsegundos.
Paso 9: Limpiar los archivos de prueba
fio no borra los archivos que crea. Elimínalos al terminar para recuperar el espacio:
rm -rf ~/fio-test
Solución de problemas
fio: looks like your file system does not support direct=1/buffered=0: el sistema de archivos (por ejemplotmpfs) no admiteO_DIRECT. Usa un directorio en un disco real.- Resultados de lectura imposibles, de varios GB/s en un disco modesto: falta
--direct=1, o el archivo de prueba es tan pequeño que cabe en la caché del controlador. Usa un--sizede varios GB. No space left on device:--sizesupera el espacio libre. Reduce el tamaño o elige otro directorio.- Las IOPS se estancan al subir
--iodepth: has alcanzado el límite del dispositivo o del plan. Subir la cola a partir de ahí solo aumenta la latencia.
Conclusión
Ahora puedes medir IOPS aleatorias, ancho de banda secuencial y latencia de fsync con fio, y tienes un archivo de trabajo que repite las mismas pruebas y guarda los resultados en JSON. Como siguientes pasos, puedes medir la base de datos completa con pgbench o sysbench oltp, comparar sistemas de archivos (ext4 frente a XFS) con el mismo archivo de trabajo, o vigilar el disco en producción con iostat -x 1 del paquete sysstat.
