Cambias un servidor de ext4 a ZFS porque quieres checksums, snapshots, send/receive y la tranquilidad de que tu almacenamiento ya no está sostenido por la esperanza.
Luego aparecen las gráficas. La latencia salta, el throughput se aplanza y el SSD que parecía un cohete en ext4 de repente se comporta como si esperara aprobación gerencial.
Esto normalmente no significa “ZFS es lento”. Es ZFS siendo honesto sobre el dispositivo, la carga de trabajo y el modelo de colas que construiste sin darte cuenta.
La profundidad de cola es donde muchas de estas incomprensiones terminan viviendo.
Qué significa realmente la profundidad de cola (y por qué te importa)
La profundidad de cola es cuántas operaciones de E/S están “en vuelo” hacia un dispositivo al mismo tiempo. Si solo tienes una petición pendiente a la vez,
básicamente estás conduciendo un coche deportivo en primera marcha mientras obedeces cuidadosamente un límite de 10 mph.
Los SSD, especialmente NVMe, están diseñados para funcionar con paralelismo. Ocultan trabajo interno (mapeo del flash translation layer, garbage collection,
wear leveling) detrás de múltiples comandos pendientes. Con baja profundidad de cola obtienes latencias decentes pero throughput mediocre. Con mayor profundidad de cola,
generalmente obtienes mayor throughput… hasta que alcanzas un acantilado y la latencia explota.
La parte que la gente pasa por alto: la profundidad de cola no es solo una propiedad de tu herramienta de benchmark. Es una propiedad emergente de toda la pila:
concurrencia de la aplicación, scheduler de E/S del kernel, comportamiento del sistema de archivos, cachés, política de writeback y firmware del dispositivo.
ext4 y ZFS difieren drásticamente en cómo generan E/S, cuándo la envían y cómo convierten escrituras aleatorias en algo que el dispositivo puede digerir.
Además, “profundidad de cola” tiene dos significados en la conversación habitual:
- Profundidad de cola en el host: cuántas peticiones ha enviado el SO pero el dispositivo no ha completado.
- Profundidad de cola en el dispositivo: cuántos comandos están en las colas del dispositivo (NVMe tiene múltiples colas de submission/completion).
Si alguna vez viste un SSD hacerlo genial a QD=1 y horrible a QD=32, felicidades: conociste la diferencia entre “rápido” y “estable”.
Por qué ext4 puede parecer más rápido
El modo operativo normal de ext4 es: aceptar escrituras, dejar que la page cache del kernel las absorba y volcarlas después mediante writeback.
Para muchas cargas, eso significa que la aplicación piensa que es rápido porque está escribiendo mayormente en RAM. Cuando llega el flush,
la capa de bloques del kernel y el scheduler pueden combinar, reordenar y hacer streaming de E/S de maneras que le gustan a tu SSD.
ZFS también hace caching, pero aplica reglas distintas. ZFS es copy-on-write y basado en transacciones. Acumula cambios en memoria,
luego los confirma en transaction groups (TXGs). También valida datos con checksums, escribe bloques nuevos en lugar de sobrescribir los antiguos
y mantiene metadatos que ext4 no necesita gestionar de la misma forma.
Esto puede ser una ventaja de rendimiento o una trampa, según tu carga y tu dispositivo:
- Ventaja: ZFS puede agregar pequeñas escrituras aleatorias en escrituras más grandes y secuenciales-ish en el commit de TXG, que los SSD suelen manejar bien.
- Trampa: ZFS puede generar ráfagas: mucha E/S llega al dispositivo a la vez, la profundidad de cola sube bruscamente y algunos SSD se desmoronan.
- Trampa: La E/S de metadatos de ZFS puede ser más intensa (especialmente bajo snapshots, bloques pequeños y conjuntos de datos con alta churn).
- Trampa: las escrituras síncronas (fsync, O_DSYNC, bases de datos) pueden ser brutalmente honestas. ext4 frecuentemente “se sale con la suya” usando ordered mode + barriers,
mientras ZFS insiste en semánticas correctas. Lo correcto puede parecer lento cuando tu hardware no está aprovisionado para ello.
Conclusión práctica: ext4 suele “parecer más rápido” en benchmarks que miden tiempo hasta el reconocimiento en lugar de tiempo hasta almacenamiento durable,
o que accidentalmente prueban la page cache. ZFS tiende a exponer el coste real de la durabilidad, especialmente para aplicaciones con muchas operaciones síncronas.
Cómo ZFS genera E/S: agregación, TXG y la brecha con la realidad
The TXG rhythm: smooth on paper, spiky in production
ZFS recoge datos sucios en memoria y periódicamente los confirma como un TXG. Ese commit es donde ZFS escribe muchas cosas:
nuevos bloques de datos, nuevos bloques de metadata, bloques indirectos actualizados, spacemaps y finalmente los uberblocks.
Si el sistema está ocupado, puedes obtener una canalización casi continua de TXGs, pero cada uno aún tiene un momento de “empuje”.
Las ráfagas no son inherentemente malas. A los SSD les gusta el paralelismo. El problema es cuando la ráfaga empuja al dispositivo hacia su peor modo de comportamiento:
garbage collection interno, agotamiento de la cache SLC, sobrecarga de gestión de colas en el firmware o throttling térmico.
ZFS no creó esas debilidades; solo las encontró más rápido que ext4.
ZIO pipeline and concurrency knobs
ZFS no envía E/S como un único flujo. Tiene una pipeline (ZIO) con etapas: checksum, compresión, gang blocks, asignación,
emisión de E/S, completado, etc. ZFS también tiene límites de concurrencia internos por vdev y por clase de E/S.
Esos límites han cambiado entre versiones de OpenZFS y sistemas operativos, pero la idea se mantiene: ZFS intenta ser justo y estable,
no “máxima profundidad de cola a toda costa”.
Si vienes de ext4 y piensas “más profundidad de cola siempre es mejor”, ZFS probablemente no estará de acuerdo contigo en producción.
ZFS suele preferir concurrencia controlada porque la concurrencia sin control se convierte en picos de latencia,
y los picos de latencia se convierten en bases de datos infelices y timeouts.
Why zvols can behave differently than datasets
Un dataset ZFS es un sistema de archivos con recordsize (por defecto a menudo 128K). Un zvol es un dispositivo de bloque con volblocksize (a menudo 8K por defecto).
Los patrones de E/S difieren, los metadatos difieren y la amplificación de escritura difiere. Con zvols puedes acabar fácilmente con
muchas escrituras pequeñas y síncronas—especialmente con imágenes de VM y bases de datos que usan fsync con frecuencia.
ext4 sobre un dispositivo de bloque crudo puede beneficiarse de writeback y reordenamiento. Un zvol puede ser más “literal”, y lo pagas.
Eso no es una falla moral. Es una decisión de ingeniería que necesitas alinear con la carga de trabajo.
Una idea parafraseada, atribuida porque es lo más parecido a una escritura sagrada en operaciones:
paráfrasis: “La esperanza no es una estrategia.”
— a menudo atribuida en círculos SRE a ingenieros en espíritu, pero aquí mantenida deliberadamente no textual.
(Y sí, deberías medir, no esperar.)
Dónde se atragantan los SSD: acantilados de latencia, límites de firmware e E/S mixtas
The latency cliff is real
Muchos SSD de consumo y prosumer están optimizados para ráfagas estilo escritorio, baja profundidad de cola y mezclas con predominio de lecturas.
Brillan en tests sintéticos sobre ext4 que no mantienen la presión lo suficiente como para activar las partes feas.
Bajo commits de TXG de ZFS o escrituras síncronas sostenidas, el dispositivo alcanza estado estable, la cache SLC se vacía
y de repente tu SSD “3 GB/s” está en modo “por favor espere” a 40–200 MB/s con latencia que hace que tu aplicación parezca poseída.
Firmware fairness vs. throughput tricks
Los SSD empresariales a menudo intercambian números máximos de benchmark por latencia de cola predecible a profundidades de cola más altas.
Son aburridos. Lo aburrido es bueno. Los SSD de consumo suelen perseguir grandes números de marketing apoyándose en caches y combinación agresiva de escrituras.
Eso puede ser genial hasta que la carga se vuelve continua y multihilo. Las cargas de ZFS con frecuencia son exactamente eso: continuas y multihilo.
Mixed reads and writes with metadata
Los metadatos de ZFS no son gratis. Los snapshots y clones pueden multiplicar el trabajo de metadatos. Las pequeñas escrituras aleatorias generan más churn de metadata.
Si tu pool está casi lleno, la asignación de espacio se complica y los spacemaps se vuelven más activos. El SSD ve una mezcla:
pequeñas lecturas por metadata, escrituras por datos y puntos sync por consistencia.
Algunos discos manejan esto con gracia. Otros lo manejan como un niño con un violín.
Chiste #1: Una vez pregunté a un SSD de consumo por su rendimiento sostenido de escritura. Respondió con throttling térmico por despecho.
Alignment and ashift: the silent performance tax
Si el ashift de tu pool no coincide con el tamaño real de sector físico del dispositivo, puedes forzar comportamiento de read-modify-write.
Eso significa que cada escritura “pequeña” puede convertirse en múltiples operaciones internas. ext4 también puede sufrir por desalineación,
pero ZFS facilita crear una misconfiguración permanente al crear el pool.
Sync write semantics: ZFS refuses to lie
La forma más rápida de hacer que ZFS “sea lento” es ejecutar una carga de trabajo con muchas escrituras síncronas en dispositivos sin protección contra pérdida de energía y sin un SLOG adecuado,
esperando a la vez comportamiento como el de ext4. ZFS respetará la petición: “haz esto durable.”
Tu SSD hará su mejor imitación de un disco giratorio.
Datos interesantes y contexto histórico
- ZFS se originó en Sun Microsystems a mediados de los 2000, diseñado para integridad de extremo a extremo y almacenamiento en pool, no para perseguir trofeos de benchmarks monohilo.
- Copy-on-write no fue inventado por ZFS, pero ZFS lo popularizó para sistemas de archivos de propósito general a escala con gestión de volúmenes integrada.
- NVMe introdujo múltiples colas hardware para reducir la contención de locks y la sobrecarga de CPU comparado con SATA/AHCI, haciendo que la profundidad de cola y la afinidad de CPU sean más visibles en rendimiento.
- Los controladores SSD tempranos eran famosos por acantilados de escritura cuando sus tablas de mapeo internas o caches se llenaban; los discos modernos son mejores, pero la forma del acantilado aún existe.
- ZFS ha usado longtime transaction groups para agrupar cambios; este agrupamiento puede mejorar throughput pero también crea ráfagas que exponen dispositivos débiles.
- Los planificadores de E/S en Linux evolucionaron de CFQ a deadline a mq-deadline y none; con NVMe, muchas pilas prefieren “none”, moviendo más comportamiento hacia dispositivo y sistema de archivos.
- Los tamaños de sector son complicados: existen 512e y 4Kn porque la industria intentó mover a sectores de 4K sin romper todo de golpe.
- El checksum de bloques de datos hace que las lecturas de ZFS a menudo se verifiquen end-to-end; esto es un trabajo de CPU pequeño pero real, y cambia cómo se percibe la “velocidad” bajo carga.
Guía rápida de diagnóstico
Cuando ZFS “se atraganta”, no empiezas cambiando tunables al azar. Empiezas encontrando qué cola se está llenando:
aplicación, ARC, ZIO, vdev, capa de bloques del kernel o el propio SSD. Aquí tienes una secuencia rápida que funciona cuando el pager está gritando.
First: identify whether you’re bound by latency, bandwidth, CPU, or sync
- Revisa latencia y encolamiento por dispositivo (iostat). Si
awaityaqu-szsuben, el dispositivo está saturado o se está comportando mal. - Revisa la espera a nivel ZFS (zpool iostat -w). Si ZFS muestra tiempos de espera altos, el cuello de botella está por debajo de ZFS, no en ARC.
- Revisa CPU y softirqs. Si la CPU está al máximo en kernel o softirq, el “problema de almacenamiento” podría ser contención de CPU.
- Revisa si la carga es sync-heavy. Si es así, trátalo primero como un problema de durabilidad.
Second: isolate which kind of I/O is hurting
- Lecturas vs escrituras: ¿las lecturas son lentas porque la metadata está thrashing?
- Pequeñas aleatorias vs grandes secuenciales: ¿recordsize/volblocksize está desajustado?
- Estado estable vs ráfaga: ¿el rendimiento se colapsa después de un minuto? Eso indica comportamiento de cache SLC/GC/throttling térmico.
Third: confirm pool layout and the non-negotiables
- Ocupación del pool: si estás por encima de ~80–90% en muchos pools, los costes de asignación suben y los SSD sufren.
ashift: ashift incorrecto es para siempre salvo que reconstruyas.- Estrategia de sync: si necesitas semánticas síncronas, usa hardware adecuado o acepta el coste.
Tareas prácticas: comandos, salidas, decisiones (12+)
Estas son las comprobaciones que ejecuto cuando alguien me dice “ext4 era más rápido”. El objetivo no es coleccionar trivia.
El objetivo es decidir qué arreglar, qué dejar y qué reconstruir.
Task 1: Confirm the device and transport (NVMe vs SATA, link speed)
cr0x@server:~$ lsblk -d -o NAME,MODEL,TRAN,ROTA,SIZE
NAME MODEL TRAN ROTA SIZE
nvme0n1 SAMSUNG_MZVLW1 nvme 0 953.9G
sda ST2000DM008 sata 1 1.8T
Qué significa: TRAN te dice si estás en NVMe o SATA; ROTA muestra si es rotacional.
Si esperabas NVMe y ves SATA, tu “problema con ZFS” podría ser un problema de compras.
Decisión: Verifica tu objetivo de prueba. No ajustes ZFS para la clase de dispositivo equivocada.
Task 2: Check kernel I/O scheduler for the device
cr0x@server:~$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline kyber bfq
Qué significa: NVMe comúnmente corre con none, lo que implica scheduling mínimo en el host.
Decisión: Si ves bfq en NVMe rápido y buscas throughput, considera none o mq-deadline.
Si buscas estabilidad de latencia bajo carga mixta, mq-deadline puede ser más sensato que “confiar en el firmware”.
Task 3: Observe queue depth and latency live (block layer view)
cr0x@server:~$ iostat -x 1 nvme0n1
avg-cpu: %user %nice %system %iowait %steal %idle
8.21 0.00 4.88 2.44 0.00 84.47
Device r/s w/s rKB/s wKB/s rrqm/s wrqm/s %util await aqu-sz
nvme0n1 1200 9000 98000 620000 0.0 0.0 99.5 6.80 62.4
Qué significa: aqu-sz es el tamaño medio de la cola; await es la latencia media.
%util cerca de 100% significa que el dispositivo está ocupado.
Decisión: Si el tamaño de cola es enorme y la latencia sube, estás saturando el dispositivo o golpeando un acantilado de firmware.
Si la cola es pequeña pero el throughput es bajo, tu cuello de botella está por encima del dispositivo (CPU, sync o throttling de ZFS).
Task 4: Check ZFS vdev latency and queueing
cr0x@server:~$ zpool iostat -v 1
capacity operations bandwidth
pool alloc free read write read write
tank 1.23T 2.41T 900 7200 110M 690M
mirror 1.23T 2.41T 900 7200 110M 690M
nvme0n1 - - 450 3600 55M 345M
nvme1n1 - - 450 3600 55M 345M
Qué significa: Esto te dice si ZFS está emitiendo E/S y cómo se distribuye entre vdevs.
Decisión: Si un leaf vdev es más lento, arrastrará todo el pool. Reemplaza al hijo problemático o re-balancea el diseño.
Task 5: Confirm pool health and error counters
cr0x@server:~$ zpool status -v
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
errors: No known data errors
Qué significa: Si tienes retries, errores de checksum o dispositivos degradados, es de esperar problemas de rendimiento.
Decisión: Arregla la fiabilidad primero. Ajustar alrededor de errores es cómo los incidentes escalan a outages.
Task 6: Check dataset properties that change I/O shape
cr0x@server:~$ zfs get -o name,property,value -s local,default recordsize,compression,atime,primarycache,sync tank/data
NAME PROPERTY VALUE
tank/data recordsize 128K
tank/data compression zstd
tank/data atime off
tank/data primarycache all
tank/data sync standard
Qué significa: recordsize afecta la amplificación de escritura para pequeñas escrituras aleatorias; sync afecta el comportamiento de durabilidad.
Decisión: Para bases de datos con páginas de 8K, considera recordsize=16K o 8K solo si entiendes el coste en metadatos.
No hagas esto por imitación; mide.
Task 7: Check zvol settings if you’re serving VM disks or iSCSI
cr0x@server:~$ zfs get -o name,property,value -s local,default volblocksize,compression,sync,logbias tank/vm0
NAME PROPERTY VALUE
tank/vm0 volblocksize 8K
tank/vm0 compression off
tank/vm0 sync standard
tank/vm0 logbias latency
Qué significa: Un volblocksize pequeño puede aumentar IOPS pero también castigar el pool con metadatos y fragmentación.
Decisión: Si ves escrituras síncronas intensas y no tienes SLOG, espera dolor. Si tienes SLOG, logbias=latency es razonable.
Task 8: Detect sync-heavy behavior from the application side
cr0x@server:~$ strace -f -tt -e trace=fdatasync,fsync,pwrite64 -p 2143
12:19:41.102334 fdatasync(7) = 0
12:19:41.104981 pwrite64(7, "...", 8192, 123904) = 8192
12:19:41.106204 fdatasync(7) = 0
Qué significa: Si ves frecuentes fsync/fdatasync, tu carga se preocupa por la durabilidad y el orden.
Decisión: Trátalo como un problema de latencia sync. Considera SLOG (con PLP), ajusta sync solo con los ojos abiertos.
Task 9: Verify SLOG presence and whether it’s actually being used
cr0x@server:~$ zpool status
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
logs
nvme2n1 ONLINE 0 0 0
Qué significa: Un dispositivo bajo logs es un intent log separado (SLOG).
Decisión: Si ejecutas cargas sync-heavy, un SLOG adecuado puede reducir la latencia de cola. Si tu SLOG es un SSD de consumo aleatorio sin PLP,
estás comprando velocidad con riesgo de integridad. No lo hagas.
Task 10: Check pool fragmentation and capacity pressure
cr0x@server:~$ zpool list -o name,size,alloc,free,cap,frag,health
NAME SIZE ALLOC FREE CAP FRAG HEALTH
tank 3.64T 3.20T 440G 87% 62% ONLINE
Qué significa: Alta cap y alta frag a menudo correlacionan con peor comportamiento de asignación y más churn de metadatos.
Decisión: Si estás cerca del lleno, deja de tunear y empieza a planear capacidad. Espacio libre es rendimiento.
Task 11: Measure ZFS ARC behavior (are you actually caching?)
cr0x@server:~$ arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
12:20:10 9850 1200 12 500 5 700 7 0 0 32.0G 32.0G
12:20:11 10310 1500 15 800 8 700 7 0 0 32.0G 32.0G
12:20:12 9980 2200 22 1600 16 600 6 0 0 32.0G 32.0G
Qué significa: Subida de miss% significa que vas al disco más a menudo.
Decisión: Si tu working set no cabe y tienes una carga de lecturas, considera más RAM o reestructurar datasets.
No agregues L2ARC como reacción primaria; puede añadir sobrecarga.
Task 12: Check TRIM/discard status (SSD steady-state behavior)
cr0x@server:~$ zpool get autotrim tank
NAME PROPERTY VALUE SOURCE
tank autotrim on local
Qué significa: autotrim=on ayuda a los SSD a mantener rendimiento informándoles de bloques liberados.
Decisión: Si autotrim está off en pools SSD y tienes churn, considera activarlo (tras validar soporte de OS/ZFS).
Task 13: Confirm ashift (alignment) on each vdev
cr0x@server:~$ zdb -C tank | grep -E 'ashift|path' -n
128: path: '/dev/nvme0n1'
135: ashift: 12
142: path: '/dev/nvme1n1'
149: ashift: 12
Qué significa: ashift: 12 corresponde a sectores de 4K. Muchos SSD requieren al menos esto.
Decisión: Si ves ashift: 9 en SSD modernos, probablemente tengas un impuesto de rendimiento permanente. Reconstruye el pool correctamente.
Task 14: Check NVMe health indicators and throttling hints
cr0x@server:~$ nvme smart-log /dev/nvme0n1
Smart Log for NVME device:nvme0n1 namespace-id:ffffffff
critical_warning : 0x00
temperature : 71 C
available_spare : 100%
percentage_used : 3%
data_units_read : 123,456,789
data_units_written : 98,765,432
host_read_commands : 4,321,000,000
host_write_commands : 7,654,000,000
controller_busy_time : 12,345
media_errors : 0
num_err_log_entries : 0
Qué significa: 71°C está coqueteando con territorio de throttling para algunos discos.
Decisión: Si el rendimiento colapsa bajo carga y la temperatura es alta, arregla el flujo de aire antes de escribir un documento de tuning.
Task 15: Reproduce with a benchmark that controls queue depth and bypasses cache
cr0x@server:~$ fio --name=randwrite --filename=/tank/data/fio.test --size=8G --direct=1 --ioengine=libaio --rw=randwrite --bs=4k --iodepth=32 --numjobs=4 --group_reporting
randwrite: (groupid=0, jobs=4): err= 0: pid=8812: Fri Dec 22 12:24:33 2025
write: IOPS=52.4k, BW=205MiB/s (215MB/s)(8192MiB/39945msec)
slat (usec): min=4, max=980, avg=18.21, stdev=9.44
clat (usec): min=50, max=120000, avg=2400.15, stdev=7800.22
lat (usec): min=60, max=120500, avg=2419.10, stdev=7800.40
Qué significa: La latencia media es 2.4ms pero el máximo es 120ms: la latencia de cola es fea.
Decisión: Si ext4 parece “más rápido”, repite el mismo perfil fio sobre ext4 con direct=1.
Si la latencia de cola en ZFS es peor, céntrate en sync, ocupación del pool, comportamiento térmico/firmware del dispositivo y desajuste del patrón de E/S.
Errores comunes: síntoma → causa raíz → solución
1) “El throughput está bien, pero la latencia salta cada pocos segundos”
Síntoma: Picos de latencia periódicos; timeouts en la aplicación; las gráficas parecen un latido.
Causa raíz: Ráfagas de commit TXG que golpean un SSD débil en estado estable (agotamiento de cache SLC, GC) o throttling térmico.
Solución: Confirma con tests steady-state de fio y temperatura NVMe. Mejora la refrigeración, elige SSD con escrituras sostenidas predecibles, mantén el pool con margen de capacidad.
2) “ext4 supera a ZFS por 2–5× en escrituras en mi prueba”
Síntoma: Copia de archivo simple o benchmark ingenuo reporta ext4 mucho más rápido.
Causa raíz: El benchmark mide page cache y delayed allocation, no durabilidad; la prueba ZFS está golpeando semánticas sync o I/O directo.
Solución: Usa direct=1 en fio, o al menos vacía caches; compara manzanas con manzanas (sync vs async, buffered vs direct).
3) “El almacenamiento de VM en zvol es lento, los datasets se ven bien”
Síntoma: IOPS aleatorias pobres, cargas fsync-heavy se quedan, los invitados se quejan.
Causa raíz: Volblocksize pequeño + carga de invitados sync-heavy + sin SLOG; también puede ser volblocksize mal ajustado al filesystem del invitado.
Solución: Añade un SLOG con PLP, considera ajustar volblocksize según la carga, valora usar datasets para algunos patrones de VM y valida expectativas de sync.
4) “Empeoró después de habilitar compresión”
Síntoma: Más CPU, menor throughput, más latencia bajo carga.
Causa raíz: La CPU se convierte en cuello de botella, o el algoritmo de compresión es demasiado costoso para el presupuesto de cores; además puede cambiar la distribución del tamaño de E/S.
Solución: Usa un algoritmo más rápido (ej., zstd en niveles bajos), mitiga la contención de CPU, mide de nuevo. La compresión no es gratis; es una compensación.
5) “Todo estaba bien hasta que el pool llegó al 85–90%”
Síntoma: Las escrituras se ralentizan, las lecturas de metadata aumentan, la fragmentación sube.
Causa raíz: La asignación se vuelve cara; los SSD ven más escrituras aleatorias; ZFS tiene menos regiones contiguas grandes.
Solución: Añade capacidad, borra/traslada datos, reduce el churn de snapshots, mantén espacio libre. El tuning no reemplaza el espacio libre.
6) “Pusimos sync=disabled y ahora va rápido”
Síntoma: El rendimiento mejora drásticamente; todos celebran.
Causa raíz: Cambiaste durabilidad por velocidad. Un crash puede perder escrituras reconocidas. En algunos sistemas puede corromper invariantes a nivel de aplicación.
Solución: Revierte salvo que tengas una razón documentada y aceptes la pérdida de datos. Usa SLOG o dispositivos mejores en su lugar.
Tres mini-historias del mundo corporativo
Mini-historia 1: El incidente causado por una suposición errónea
Una compañía SaaS mediana movió un clúster PostgreSQL ocupado de ext4 en RAID10 a espejos ZFS en “NVMe rápido”.
El plan de migración era sólido: snapshots, puntos de rollback, corte controlado, lo de siempre.
La suposición no dicha: “NVMe es NVMe, funcionará.”
En horas, vieron stalls periódicos en consultas. No lentitud constante—peor. Pausas aleatorias de 2–10 segundos que agotaron pools de conexiones.
Los logs de la base mostraban ráfagas de fsync lentos. El SO estaba tranquilo. La CPU estaba bien. La red estaba bien. Las gráficas de almacenamiento parecían un sismógrafo.
La causa raíz no era la sobrecarga correcta de ZFS. Era el comportamiento de escritura sostenida del modelo de SSD bajo presión sync sostenida.
Bajo ext4, la carga había sido “suavizada” por la page cache y el writeback; el controlador RAID (con batería) también ayudaba.
Bajo ZFS, con semánticas sync correctas y sin dispositivo de log dedicado, el pool forzó a los SSD a mostrar su verdadera latencia de cola.
La solución fue poco glamorosa: añadir dispositivos de log con protección contra pérdida de energía, ajustar el layout del pool para la carga,
y reemplazar el modelo de SSD peor por discos con latencia sostenida predecible.
La lección del postmortem fue menos glamorosa aún: las listas de compra ahora incluyen pruebas de escritura sostenida, no solo IOPS de la hoja de especificaciones.
Mini-historia 2: La optimización que salió mal
Un equipo de plataforma interno gestionaba un clúster de virtualización multi-tenant. Estaban orgullosos de sus habilidades con ZFS y querían máximo rendimiento.
Vieron un post en un foro que decía, más o menos, “aumentad la concurrencia; ZFS es conservador.”
Ajustaron varios parámetros del módulo ZFS para permitir colas más profundas y más E/S pendientes por vdev.
En benchmarks de un solo tenant, parecía genial. El throughput subió. Todos compartieron capturas. Luego volvió la carga real:
docenas de VMs haciendo lecturas, escrituras y ráfagas sync mezcladas. La latencia de cola empeoró. No un poco: bastante.
“Usuarios abriendo tickets por lentitud.”
El sistema se había vuelto excelente saturando los SSD y terrible manteniendo latencia predecible.
Bajo carga mixta, las colas más profundas causaron agrupamiento de peticiones. El firmware del SSD respondió con reordenamiento interno y pausas largas de garbage collection.
Las métricas medias parecían bien. El percentil 99.9 parecía un incendio.
Revirtieron los cambios y se centraron en la aislamiento de carga: pools separados para vecinos ruidosos,
SLOGs apropiados para tenants sync-heavy y dejar las limitaciones por defecto de ZFS a menos que tuvieran una razón medida.
El rendimiento “disminuyó” en tests sintéticos, y la plataforma mejoró en la única métrica que importa a los usuarios: menos stalls.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Una compañía relacionada con finanzas (lo que significa auditorías y memorias largas) ejecutaba ZFS para una pipeline de ingestión de logs.
Poco glamuroso. Mayormente escrituras secuenciales con compactaciones periódicas. Tenían una política: nunca ejecutar pools por encima del 75%,
siempre mantener autotrim en pools SSD y siempre probar nuevos modelos de SSD con escrituras sostenidas de 30 minutos antes de aprobarlos.
Un trimestre, un proveedor sustituyó un modelo de SSD “más nuevo” por problemas de suministro. En papel era más rápido.
El equipo ejecutó su prueba steady-state de todos modos. En el minuto 12, la latencia de escritura saltó un orden de magnitud y se mantuvo.
El disco no estaba fallando; simplemente hacía lo que hace cuando su cache y tablas de mapeo se ven bajo presión sostenida.
Rechazaron la sustitución y mantuvieron el modelo antiguo. Un mes después, otro departamento desplegó el modelo sustituto en un sistema distinto
y pasó semanas persiguiendo timeouts intermitentes. El equipo de ZFS no tuvo que decir “te lo dije” en voz alta.
El proceso aburrido—margen de capacidad, política de trim y pruebas steady-state—previno un incidente lento pero persistente.
Chiste #2: El mejor tuning de rendimiento a veces es una hoja de cálculo y la habilidad de decir “no”, por eso se aplica tan rara vez.
Listas de verificación / plan paso a paso
Step-by-step: reproduce the ext4 vs ZFS claim without lying to yourself
- Elige el mismo dispositivo y estilo de particionado. No compares ext4 en un disco crudo con ZFS en un zvol escaso a menos que eso sea intencional.
- Ejecuta tests de I/O directo primero. Usa fio con
direct=1para medir dispositivo + sistema de archivos, no RAM. - Prueba a múltiples profundidades de cola. QD=1, 4, 16, 32. Observa dónde la latencia se rompe. Ese punto de ruptura importa más que los IOPS pico.
- Corre lo suficiente para alcanzar estado estable. Minutos, no segundos. Muchos acantilados SSD aparecen después de que se agotan caches.
- Separa tests sync vs async. Si tu carga hace fsync, prueba fsync. Si no, no te castigues con tests sync.
Step-by-step: production-safe tuning order (least regret first)
- Arregla realidades de hardware/firmware. Refrigeración, clase correcta de SSD, evita discos baratos para cargas sync-heavy.
- Arregla capacidad y diseño del pool. Margen, diseño de vdev, espejos vs RAIDZ según necesidades de latencia.
- Arregla desajustes obvios de dataset. recordsize/volblocksize, atime, nivel de compresión.
- Gestiona semánticas sync correctamente. SLOG con PLP, o acepta el coste de rendimiento.
- Solo entonces toca los tunables internos profundos de ZFS. Y hazlo con planes de rollback y resultados medidos.
Checklist: before you blame ZFS
- ¿Estás comparando escrituras buffered en ext4 vs escrituras durables en ZFS?
- ¿El pool está por encima del 80–85% de capacidad o muy fragmentado?
- ¿La temperatura del SSD es alta bajo carga?
- ¿La carga hace fsync/fdatasync frecuente?
- ¿Es correcto el ashift?
- ¿Estás usando zvols donde datasets serían más simples (o viceversa)?
- ¿Tienes SSD empresariales predecibles o modelos de consumo con picos?
Preguntas frecuentes
1) ¿ZFS “usa menor profundidad de cola” por diseño?
ZFS tiende a gestionar la concurrencia para proteger latencia y equidad. Puede generar alta profundidad de cola bajo carga, pero intenta no llevar al dispositivo al colapso.
Si tu SSD necesita QD extremo para rendir, esa es una característica del dispositivo que deberías validar en estado estable.
2) ¿Por qué algunos SSD rinden muy bien en ext4 y mal en ZFS?
Los benchmarks en ext4 a menudo golpean la page cache y el delayed writeback, enmascarando acantilados del dispositivo. ZFS puede empujar patrones más veraces: ráfagas en commits TXG,
más churn de metadata y comportamiento explícito de sync. Los SSD débiles en estado estable quedan expuestos.
3) ¿Debería cambiar el scheduler de E/S de Linux para NVMe al usar ZFS?
A veces. “none” es común y a menudo suficiente. Si necesitas estabilidad de latencia bajo cargas mixtas, mq-deadline puede ayudar.
No esperes milagros; los tweaks de scheduler no arreglan un disco que colapsa bajo escrituras sostenidas.
4) ¿Agregar un SLOG siempre mejora el rendimiento?
Solo para escrituras síncronas. Para cargas mayoritariamente asíncronas, SLOG hace poco. Para cargas sync-heavy, un SLOG PLP adecuado puede reducir mucho la latencia de cola.
Un SLOG sin PLP es una apuesta por la fiabilidad, no una optimización.
5) ¿Los zvols son inherentemente más lentos que los datasets?
No inherentemente, pero se comportan diferente. Los zvols pueden amplificar pequeñas escrituras aleatorias y patrones sync. Los datasets pueden agregar escrituras más naturalmente.
Elige según la carga: imágenes de VM e iSCSI suelen preferir zvols; cargas de archivos suelen preferir datasets.
6) ¿Cuál es el mayor “oops” que causa dolor con SSD en ZFS?
Ejecutar carga sync-heavy en SSD de consumo sin PLP y sin un SLOG real, esperando baja latencia de cola.
En segundo lugar, llenar los pools demasiado y preguntarse por qué la asignación es lenta.
7) ¿Debería ajustar recordsize a 8K para bases de datos?
A veces, pero no es gratis. Recordsize menor puede reducir amplificación de lectura para lecturas pequeñas pero aumenta metadatos y riesgo de fragmentación.
Muchas bases de datos funcionan bien con 16K o 32K; algunas necesitan 8K. Mide con concurrencia realista y tests steady-state.
8) ¿Cómo sé si estoy viendo un acantilado de cache SLC del SSD?
Ejecuta una prueba de escritura sostenida lo bastante larga (10–30 minutos) con I/O directo y una profundidad de cola realista.
Si el throughput cae bruscamente después de un corto periodo y la latencia se dispara, es comportamiento clásico de agotamiento de cache o GC.
9) ¿Es seguro habilitar autotrim?
En OpenZFS y SSD modernos, autotrim es de uso común y ayuda al rendimiento en estado estable. Aun así, valida en tu entorno.
Si tienes firmware antiguo o capas de virtualización extrañas, prueba primero.
10) ¿Por qué el rendimiento cambia con snapshots?
Los snapshots incrementan el trabajo de metadatos y pueden aumentar la fragmentación bajo churn. Las eliminaciones son más caras porque los bloques están referenciados por snapshots.
Esto puede cambiar el comportamiento de escritura e incrementar la E/S aleatoria, que algunos SSD manejan mal a profundidades de cola altas.
Conclusión: siguientes pasos que puedes hacer hoy
Si un SSD “vuela en ext4 y se atraganta en ZFS”, probablemente estés viendo una de tres cosas: un benchmark que halaga ext4 probando cache,
una comprobación de latencia sync, o un SSD que colapsa bajo E/S mixta sostenida cuando la profundidad de cola sube.
ZFS rara vez es el villano. Es el auditor.
Haz esto a continuación:
- Re-prueba con fio usando I/O directo a múltiples profundidades de cola y el tiempo suficiente para alcanzar estado estable.
- Captura iostat y zpool iostat durante la desaceleración y decide si el cuello de botella es saturación del dispositivo, latencia sync o CPU/overhead de interrupciones.
- Revisa headroom del pool y ashift; si estás demasiado lleno o desalineado, arregla el diseño, no los síntomas.
- Si sync es el problema, soluciona correctamente: SLOG PLP, SSD mejores, o acepta que la durabilidad tiene un coste.
- Resiste ajustar al azar. Ajusta solo después de poder explicar qué cola se está llenando y por qué.
ZFS es un sistema para gente que prefiere la realidad sobre las sensaciones. Si quieres sensaciones, compra un benchmark de marketing y enmárcalo.