ZFS ARC vs caché de páginas de Linux: quién gana y por qué deberías preocuparte

¿Te fue útil?

Las guerras de caché rara vez se ganan en benchmark y con frecuencia se pierden en producción a las 2 a.m., cuando el gráfico del almacenamiento parece un sismógrafo y el equipo de bases de datos empieza a decir “debe ser la red”.
ZFS tiene el ARC. Linux tiene la caché de páginas. Ambos son muy buenos en lo suyo, y ambos pueden arruinarte el día si asumes que son la misma cosa con distinto nombre.

Este texto trata de la verdad práctica: qué almacena cada caché realmente, cómo se comportan bajo presión, por qué a veces ves “doble caché” y cómo decidir quién debe retener memoria en una carga mixta.
Tendrás historia, mecanismos, relatos de incidentes basados en patrones reales de operaciones, comandos concretos y un playbook de diagnóstico rápido que puedes usar antes de que alguien sugiera “simplemente añade RAM”.

Las dos cachés, en una frase

La caché de páginas de Linux guarda datos de archivos tal como el kernel los ve a través del VFS, de forma amplia y oportunista; ARC de ZFS guarda objetos y metadatos de ZFS dentro de la pila ZFS, de forma agresiva y con sus propias reglas.
En la práctica: la caché de páginas es el “cerebro por defecto” del SO para mantener cosas a mano; ARC es el “sé lo que necesitaré después” de ZFS—a veces más inteligente, a veces terco.

Broma #1 (rápida, relevante): preguntar “qué caché es mejor” es como preguntar si una carretilla elevadora supera a una camioneta pickup. Si mueves palets, te impresiona la carretilla—hasta que intentas conducirla por la autopista.

Hechos interesantes e historia breve (que realmente importa)

El caching no es nuevo, pero los detalles de dónde y cómo se implementa moldean los modos de fallo operativos. Algunos puntos concretos que tienden a cambiar decisiones:

  1. ZFS nació en el mundo Solaris, donde el sistema de archivos y el gestor de volúmenes estaban estrechamente integrados. ARC es parte de ese diseño integrado, no una caché “al estilo Linux” añadida.
  2. ARC es adaptativo: está diseñado para balancear entre datos usados recientemente y datos usados frecuentemente (aproximadamente comportamiento MRU vs MFU). Esa adaptabilidad es una ventaja—y una fuente de sorpresas.
  3. ZFS suma checksums a todo y puede auto-repararse con redundancia. Eso significa que las lecturas no son solo “leer bytes”; hay metadatos y sobrecarga de verificación que el caching puede amplificar o reducir.
  4. La caché de páginas de Linux es anterior a muchos sistemas de archivos actuales. Está profundamente integrada en las expectativas de rendimiento de Linux; muchas aplicaciones dependen de ella silenciosamente aunque no lo mencionen.
  5. Históricamente, ZFS en Linux tuvo que conciliar dos gestores de memoria: la VM de Linux y el propio comportamiento del ARC de ZFS. ZoL/OpenZFS moderno es mucho mejor que en los primeros días, pero el modelo de “dos cerebros” todavía importa.
  6. L2ARC llegó más tarde cuando los SSD se volvieron viables como caché de lectura. No es “más ARC”; es una extensión con costes propios, incluyendo sobrecarga de metadatos y tiempo de calentamiento.
  7. ZIL y SLOG tratan sobre escrituras síncronas, no sobre caching de lectura. Aún así, hay quien compra “un SLOG rápido” para arreglar latencia de lectura, lo cual es como instalar un buzón mejor para mejorar la acústica de la sala.
  8. Direct I/O y rutas de bypass en Linux evolucionaron junto con las bases de datos. Muchos motores DB aprenden a evitar la caché de páginas deliberadamente; ZFS tiene sus propias maneras de trabajar en ese espacio, pero no todas las combinaciones son felices.
  9. Linux moderno corre con cgroups por todas partes. ARC históricamente no siempre se comportó como “buen ciudadano” dentro de límites de memoria; las versiones más nuevas mejoraron, pero los equipos de operaciones todavía sufren expectativas desajustadas.

Un modelo mental: qué vive dónde

Cuando una aplicación lee un archivo, puedes imaginar una ruta de capas: app → libc → kernel VFS → filesystem → block layer → disco. La caché de páginas de Linux se sitúa cerca del lado VFS y cachea páginas de archivos indexadas por inode/desplazamientos de página.
ZFS, sin embargo, tiene su propia canalización: DMU (Data Management Unit) objetos, dnodes, buffers ARC, planificador de I/O de vdev, y el pool. ARC cachea al nivel de ZFS, no meramente “páginas de archivo”.

Esa diferencia tiene tres consecuencias operativas:

  • Los metadatos ganan: los metadatos de ZFS (dnodes, bloques indirectos, spacemaps) pueden almacenarse en ARC, y cachear metadatos puede cambiar radicalmente el rendimiento de lecturas aleatorias. La caché de páginas de Linux también cachea metadatos, pero los metadatos de ZFS son… más.
  • La compresión/encriptación cambia la economía: ARC puede mantener buffers comprimidos según la configuración; la caché de páginas suele mantener páginas de archivo descomprimidas tal como las ve la aplicación.
  • Las señales de expulsión y presión difieren: la VM de Linux puede recuperar la caché de páginas bajo presión con facilidad. ARC puede reducirse, pero su ajuste y heurísticas pueden no alinearse con lo que el resto del sistema considera “presión”.

Profundización en ZFS ARC (qué cachea y por qué es raro)

Qué cachea realmente ARC

ARC no es “un disco RAM para tus archivos”. Cachea buffers de ZFS: bloques de datos y bloques de metadatos tal como existen dentro de la canalización ZFS. Esto incluye datos de archivos, pero también el andamiaje necesario para encontrar datos de archivo rápidamente:
estructuras dnode, punteros a bloques indirectos y más.

En términos operativos, ARC es la razón por la que un pool ZFS que parecía “en llamas” durante un escaneo intensivo en metadatos de repente se calma una vez caliente: la segunda pasada es mayormente seguir punteros en RAM en lugar de en disco.

La política adaptativa de ARC (MRU/MFU) y por qué ves “fallos de caché” que no son errores

ARC equilibra entre buffers “usados recientemente” y “usados frecuentemente”. También rastrea listas fantasma—cosas que expulsó recientemente—para aprender si tomó la decisión correcta. Esto es inteligente y normalmente útil.
Pero significa que ARC puede parecer que está trabajando incluso cuando “está funcionando como fue diseñado”.

Los operadores a menudo interpretan mal la tasa de aciertos de ARC como un KPI universal. No lo es. Una baja tasa de aciertos puede estar bien si tu carga es streaming de archivos grandes una sola vez. Una alta tasa de aciertos puede ser engañosa si estás cacheando accidentalmente una carga que debería transmitirse secuencialmente con retención mínima.

Tamaño de ARC: la parte que provoca discusiones

En Linux, ARC compite con todo lo demás: caché de páginas, memoria anónima, slab y tus aplicaciones. ARC tiene límites (zfs_arc_max y afines), y puede reducirse bajo presión, pero el tiempo importa.
Cuando la presión de memoria llega rápido (arranca un job por lotes, un sort enorme, picos de contenedores), ARC podría no reducirse lo suficientemente rápido, y el kernel empezará a recuperar memoria en otros sitios—a veces la caché de páginas, a veces páginas anónimas—llevando a picos de latencia o incluso eventos OOM.

La pregunta práctica de ajuste no es “¿qué tan grande puede ser ARC?” Es “¿qué tan grande puede ser ARC sin desestabilizar el resto de la máquina?”

ARC y comportamiento de escritura: no es lo mismo que la caché de páginas

La caché de páginas de Linux está fuertemente acoplada al writeback y al contabilizado de páginas sucias. ZFS tiene sus propios transaction groups (TXGs), límites de datos sucios y una canalización donde los datos se preparan, escriben y confirman.
ARC en sí se centra principalmente en lecturas, pero la historia de la memoria del sistema incluye datos sucios en vuelo y actualizaciones de metadatos.

Por eso “memoria libre” es la métrica equivocada en sistemas ZFS. Te importa la recuperabilidad y la latencia bajo presión, no si la máquina parece vacía en un panel.

L2ARC: la caché SSD que se comporta como una RAM lenta secundaria

L2ARC extiende ARC a dispositivos rápidos, típicamente SSDs. Puede ayudar en lecturas aleatorias cuando el conjunto de trabajo es más grande que la RAM y cuando el patrón de acceso tiene reutilización.
Pero no es magia: L2ARC debe poblarse (calentamiento), puede aumentar la presión de memoria por el seguimiento de metadatos, y añade carga I/O al dispositivo de caché.

En producción, la decepción más común con L2ARC es esperar que arregle una carga que consiste mayormente en lecturas únicas. No puedes cachéar una petabyte que lees una sola vez.

Profundización en la caché de páginas de Linux (qué cachea y por qué está en todas partes)

Descripción del trabajo de la caché de páginas

La caché de páginas de Linux guarda páginas respaldadas por archivos: los bytes exactos que se devolverían a un proceso que lee un archivo (tras la traducción del sistema de archivos). También cachea metadatos y entradas de directorio mediante las caches dentry y inode.
Su poder viene de ser la predeterminada: casi todos los sistemas de archivos y casi todas las aplicaciones se benefician automáticamente.

Recuperación y writeback: la caché de páginas está diseñada para ser sacrificada

Linux trata la caché de páginas como reclaimable. Bajo presión de memoria, el kernel puede soltar páginas limpias de la caché rápidamente. Las páginas sucias deben escribirse, lo que introduce latencia y I/O.
Por eso ajustar el “dirty ratio” puede cambiar las latencias de cola en sistemas con mucha escritura.

La caché de páginas es un ecosistema con la VM: kswapd, reclaim directo, throttling de sucios y contabilización por cgroup (en muchas configuraciones). Por eso Linux suele sentirse “autoequilibrante” en comparación con sistemas donde las cachés están más aisladas.

Read-ahead y cargas secuenciales

La caché de páginas es buena en reconocer patrones de acceso secuencial y hacer read-ahead. Esto es una gran ventaja para lecturas en streaming.
También explica por qué tu benchmark que lee un archivo dos veces parece “increíble” la segunda vez—a menos que evites la caché de páginas o el archivo sea demasiado grande.

Direct I/O y motores de bases de datos

Muchas bases de datos usan direct I/O para evitar doble buffering y controlar su propio caching. Esto tiene sentido cuando la caché del DB está madura y el patrón de acceso es aleatorio.
Pero también traslada la responsabilidad de la corrección y el ajuste del caching a la aplicación, lo cual es genial hasta que lo ejecutas en una VM con vecinos ruidosos.

Entonces, ¿quién gana?

La respuesta honesta: ninguno “gana” de forma global. La respuesta útil operativamente: ARC tiende a ganar cuando los metadatos de ZFS y la inteligencia a nivel ZFS dominan el rendimiento, mientras que la caché de páginas tiende a ganar cuando la carga está orientada a archivos, es secuencial y encaja claramente en el modelo VFS.

ARC “gana” cuando:

  • Los metadatos importan: muchos archivos pequeños, snapshots, clones, recorridos de directorios, lecturas aleatorias que requieren recorrer árboles de bloques.
  • Están activas las funciones de ZFS: compresión, checksums, snapshots, ajuste de recordsize—ARC cachea los bloques “reales” y metadatos en el formato que ZFS necesita.
  • Quieres que ZFS decida: aceptas que el sistema de archivos sea un participante activo, no un simple almacén de bytes.

La caché de páginas de Linux “gana” cuando:

  • La carga es streaming: grandes lecturas secuenciales, pipelines de media, lecturas de backup, transferencia masiva ETL.
  • Las aplicaciones esperan la semántica de la VM de Linux: mucho software está afinado asumiendo reclaim de la caché de páginas y comportamiento de cgroups.
  • No usas ZFS: sí, obvio, pero vale la pena decirlo—la caché de páginas es la estrella por defecto para ext4/xfs y similares.

El verdadero duelo es “quién coopera mejor bajo presión”

La mayoría de incidentes en producción no tratan sobre rendimiento en estado estable. Tratan sobre qué ocurre cuando la carga cambia de repente:
arranca una reindexación, comienza un backup, escala un contenedor, un nodo está resilverizando, un job descontrolado lee todo el dataset una vez.

El “ganador” es el sistema de caching que degrada de forma gradual ante ese cambio. En Linux con ZFS, eso significa hacer que ARC sea un buen ciudadano para que la VM del kernel no tenga que hacer reclaim de pánico en el peor momento.

La trampa del “doble caché” (y cuándo está bien)

Si ejecutas ZFS en Linux y accedes a archivos de forma normal, puedes acabar con caching en múltiples capas: ARC de ZFS cachea bloques y metadatos; la caché de páginas de Linux también puede cachear páginas de archivo dependiendo de cómo ZFS se integre con el VFS.
Los detalles dependen de la implementación y la configuración, pero la verdad operativa es consistente: puedes gastar RAM dos veces para recordar el mismo contenido.

El doble caché no siempre es malvado. Puede ser inofensivo si la RAM sobra y el conjunto de trabajo es estable. Puede ser beneficioso si cada caché retiene “formas” diferentes de datos (metadatos vs páginas de archivo) que ayudan de distintas maneras.
Se convierte en un problema cuando la presión de memoria fuerza expulsión y reclaim en un bucle de retroalimentación: ARC se aferra; la VM recupera la caché de páginas; las aplicaciones hacen page faults; se realizan más lecturas; ARC crece; repite.

Broma #2: el doble caché es como imprimir el mismo informe dos veces “por si acaso”. Suena prudente hasta que te quedas sin papel y el director financiero quiere la hoja de cálculo del presupuesto ahora.

Tres mini-historias del mundo corporativo

Mini-historia #1: El incidente causado por una suposición errónea (“Memoria libre significa que estamos bien”)

Un equipo con el que trabajé ejecutaba una plataforma analítica multi-tenant en nodos Linux respaldados por ZFS. Los paneles eran reconfortantes: el uso de memoria parecía alto pero estable, el swap era bajo y el servicio había ido bien durante meses.
Entonces llegó un cambio trimestral de carga: un cliente empezó a ejecutar scans más amplios en particiones antiguas, y un nuevo proceso por lotes hizo enumeración agresiva de archivos para informes de cumplimiento.

La latencia se disparó. No solo un poco—la latencia de cola pasó de “nadie se queja” a “tickets de soporte cada cinco minutos”. La primera respuesta fue clásica: “Pero tenemos RAM. Mira, aún hay memoria libre”.
La segunda respuesta también fue clásica: reiniciar un nodo. Mejoró por una hora, luego volvió a caer en picado.

La suposición errónea era que “memoria libre” era el indicador principal, y que las cachés cederían educadamente cuando las aplicaciones necesitaran memoria. En realidad, el sistema entró en una tormenta de reclaim:
ARC mantenía una gran porción, la caché de páginas se recuperó agresivamente, y la propia presión de memoria de la aplicación causó fallos menores frecuentes y relecturas. Mientras tanto, ZFS estaba haciendo trabajo real: recorridos de metadatos, verificación de checksums e I/O aleatorio que hacía parecer culpables a los discos.

La solución no fue heroica. Limitaron ARC para dejar margen, vigilaron métricas de presión de memoria en lugar de “memoria libre”, y cambiaron el horario del job por lotes para que no coincidiera con el pico interactivo.
La lección real: en una carga mixta, “memoria disponible” y “comportamiento de reclaim bajo presión” importan más que el tamaño absoluto de RAM.

Mini-historia #2: La optimización que salió mal (“Añadamos L2ARC, será más rápido”)

Otra organización tenía un pool ZFS en SSD decentes pero aún quería más rendimiento de lectura para un índice de búsqueda. Alguien propuso añadir un L2ARC grande porque “más caché siempre es mejor”.
Instalaron un NVMe grande como L2ARC y vieron subir las tasas de acierto el primer día. Todos se sintieron listos.

Una semana después, empezaron a ver picos periódicos de latencia durante las horas pico de consultas. No había saturación de CPU. El NVMe no estaba al máximo. Los discos del pool no estaban agotados.
Los picos eran raros: cortos, agudos y difíciles de correlacionar con una única métrica.

El problema vino de dos lados. Primero, su conjunto de trabajo tenía churn: la carga de búsqueda tenía ráfagas de términos nuevos y operaciones periódicas de re-rank completas. L2ARC se poblaba con datos que no se reutilizarían.
Segundo, el sistema pagaba sobrecarga de memoria para rastrear y alimentar L2ARC, lo que estrechó los márgenes de memoria. Bajo presión, ARC y la VM del kernel empezaron a pelear. El síntoma no fue “siempre lento”, fue “picos e impredecible”, que es lo peor en SLAs corporativos.

Retiraron L2ARC, aumentaron RAM en su lugar (aburrido pero efectivo), y ajustaron recordsize y compresión para el layout del índice. El rendimiento mejoró y, más importante, se volvió predecible.
La lección: L2ARC puede ayudar, pero no es gratis, y no arregla una carga con mucho churn. Si tu dispositivo de caché está ocupado cacheando cosas que no volverás a pedir, has construido un calentador muy caro.

Mini-historia #3: La práctica aburrida pero correcta que salvó el día (“Mide antes de ajustar”)

Un servicio del ámbito financiero (piensa: liquidaciones por lotes, logs de auditoría estrictos) corría en ZFS con mezcla de escrituras síncronas pequeñas y jobs periódicos de conciliación intensivos en lectura.
Tenían una cultura de cambios que algunos ingenieros bromeaban que era “a cámara lenta”, pero tenía un hábito que me encanta: antes de cualquier cambio de rendimiento, capturaban un paquete de pruebas estándar.

Cuando sufrieron una caída repentina tras una actualización del kernel, no empezaron con perillas de ajuste. Recuperaron su paquete: estadísticas ARC, presión de VM, latencia de dispositivos, estado del pool ZFS y métricas de aplicación de alto nivel—mismos comandos, mismas ventanas de muestreo que antes.
En una hora tenían algo raro en ops: un diff limpio.

El diff mostró que el dimensionamiento de ARC no cambió, pero el comportamiento de la caché de páginas sí: el timing del writeback sucio cambió bajo el nuevo kernel, lo que interactuó con su patrón de escrituras síncronas e incrementó la latencia de escritura.
Porque tenían evidencia base, pudieron decir “es el writeback” en vez de “el almacenamiento es lento”, y validar las soluciones sin superstición.

La solución fue conservadora: ajustar parámetros de writeback dentro de límites seguros y verificar la salud del dispositivo SLOG (había empezado a reportar latencia intermitente).
El servicio se mantuvo estable, los auditores tranquilos y nadie tuvo que declarar una sala de incidentes por tres días. La lección: rituales de medición aburridos vencen a conjeturas de ajuste emocionantes.

Tareas prácticas: comandos e interpretación (al menos 12)

El objetivo de estas tareas no es “recopilar estadísticas”. Es responder preguntas específicas: ¿ARC está dominando la memoria? ¿La caché de páginas está thrashing? ¿Estamos limitados por latencia de disco, CPU o reclaim?
Los comandos abajo asumen Linux con OpenZFS instalado donde corresponda.

Tarea 1: Ver la realidad de la memoria (no el mito de “libre”)

cr0x@server:~$ free -h
              total        used        free      shared  buff/cache   available
Mem:           125Gi        42Gi       2.1Gi       1.2Gi        80Gi        78Gi
Swap:            8Gi       256Mi       7.8Gi

Interpretación: “available” es la línea clave para “cuánto podrían obtener las apps sin hacer swap”, pero sigue siendo una simplificación.
Un sistema puede mostrar bastante “available” y aun así sufrir tormentas de reclaim si la demanda de memoria sube rápido o si grandes partes no son recuperables con rapidez.

Tarea 2: Confirmar tamaño, objetivo y límites de ZFS ARC

cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c_min|c_max|c)\s'
size                            4    68719476736
c                               4    75161927680
c_min                           4    17179869184
c_max                           4    85899345920

Interpretación: size es el tamaño actual del ARC. c es el objetivo actual del ARC. c_min/c_max son los límites.
Si size se acerca a c_max durante periodos ocupados y la máquina experimenta presión de memoria, probablemente necesites un tope o más RAM—o un cambio de carga.

Tarea 3: Vigilar el comportamiento de ARC en el tiempo (misses vs hits)

cr0x@server:~$ arcstat 1 5
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:00:01   12K  2.4K     19  1.1K   9  1.0K   8  280    2   64G    70G
12:00:02   10K  2.0K     20  900    9  850    8  250    2   64G    70G
12:00:03   11K  2.2K     20  1.0K   9  950    9  260    2   64G    70G
12:00:04   13K  2.5K     19  1.2K   9  1.1K   8  290    2   64G    70G
12:00:05   12K  2.3K     19  1.1K   9  1.0K   8  270    2   64G    70G

Interpretación: El porcentaje de misses por sí solo no es un veredicto. Mira cambios: ¿las misses saltaron cuando empezó el job? ¿Las misses de datos son altas (streaming) o las de metadatos son altas (recorridos de árboles)?
Si arcsz es estable pero las misses se disparan, tu conjunto de trabajo puede exceder ARC o tu patrón de acceso tiene baja reutilización.

Tarea 4: Identificar presión de memoria y tormentas de reclaim (VM pressure)

cr0x@server:~$ cat /proc/pressure/memory
some avg10=0.12 avg60=0.20 avg300=0.18 total=9382321
full avg10=0.00 avg60=0.01 avg300=0.00 total=10231

Interpretación: PSI (Pressure Stall Information) te indica si las tareas se bloquean porque la memoria no puede asignarse con rapidez.
Un some en aumento sugiere actividad de reclaim; un full en aumento significa que el sistema frecuentemente está incapaz de proceder—aquí es donde la latencia se dispara.

Tarea 5: Capturar síntomas de kswapd/reclaim directo rápidamente

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 262144 2200000 120000 78000000  0    0   120   900 3200 6400 12  6 78  4  0
 3  1 262144 1900000 115000 77000000  0    0   220  2100 4100 9000 14  9 62 15  0
 4  2 262144 1700000 112000 76000000  0   64   450  9800 5200 12000 18 12 44 26  0
 2  1 262144 1600000 110000 75000000  0    0   300  6000 4700 10500 16 10 55 19  0
 1  0 262144 2100000 118000 77000000  0    0   160  1400 3600 7200 13  7 76  4  0

Interpretación: Observa si/so (swap in/out), wa (I/O wait) y la columna “b” (procesos bloqueados).
Una tormenta de reclaim suele mostrarse como aumento de procesos bloqueados, incremento del cambio de contexto y I/O errático.

Tarea 6: Ver la caché de páginas, slab y memoria recuperable

cr0x@server:~$ egrep 'MemAvailable|Cached:|Buffers:|SReclaimable:|Slab:' /proc/meminfo
MemAvailable:   81654312 kB
Buffers:          118432 kB
Cached:         79233412 kB
Slab:            3241120 kB
SReclaimable:    2015540 kB

Interpretación: Un gran Cached no es inherentemente malo. Un gran Slab tampoco tiene por qué ser anormal.
Pero si MemAvailable es bajo mientras ARC es alto, puede que estés apretando la VM. Si MemAvailable está bien pero PSI es alto, podrías tener fragmentación, stalls de writeback o contención por cgroups.

Tarea 7: Comprobar la salud del pool ZFS y trabajo latente (scrub/resilver)

cr0x@server:~$ zpool status -v
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:11:34 with 0 errors on Tue Dec 24 03:14:11 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

Interpretación: Un pool en resilver o un scrub durante el pico puede convertir la “discusión de cachés” en “combate del planificador de I/O”.
Compruébalo siempre al principio; de lo contrario estarás ajustando ARC mientras el pool hace el equivalente moral de reconstruir un motor conduciendo.

Tarea 8: Medir latencia de disco en la capa de bloques

cr0x@server:~$ iostat -x 1 3
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          13.22    0.00    7.11   18.90    0.00   60.77

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   w_await aqu-sz  %util
sda             220.0   18432.0     2.0   0.90    9.20    83.78    70.0    9216.0   18.40   2.10  88.0
nvme0n1        1600.0  102400.0   120.0   6.98    0.40    64.00   800.0   51200.0    0.60   0.90  35.0

Interpretación: Un alto r_await/w_await y alto %util sugiere saturación o cola en el dispositivo.
Si los discos están bien pero la latencia es alta en la app, mira la presión de memoria, CPU y la contención interna de ZFS.

Tarea 9: Inspeccionar propiedades de datasets ZFS que cambian la dinámica de caching

cr0x@server:~$ zfs get -o name,property,value -s local,default recordsize,primarycache,secondarycache,compression tank/data
NAME       PROPERTY        VALUE
tank/data  compression     lz4
tank/data  primarycache    all
tank/data  recordsize      128K
tank/data  secondarycache  all

Interpretación: recordsize moldea la granularidad de I/O y caching para archivos. Para bases de datos, a menudo quieres records más pequeños (p. ej., 16K) para reducir la amplificación de lectura.
primarycache controla lo que entra en ARC (all, metadata, none). Es una palanca importante.

Tarea 10: Limitar ARC de forma segura (opción persistente del módulo)

cr0x@server:~$ echo "options zfs zfs_arc_max=34359738368" | sudo tee /etc/modprobe.d/zfs-arc-max.conf
options zfs zfs_arc_max=34359738368

cr0x@server:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.0-xx-generic

Interpretación: Esto limita ARC a 32 GiB (el valor está en bytes). Lo haces cuando el crecimiento de ARC amenaza la memoria de las aplicaciones o provoca tormentas de reclaim.
Tras reiniciar, confirma mediante arcstats. No adivines; verifica.

Tarea 11: Ajustar primarycache para proteger RAM de lecturas en streaming

cr0x@server:~$ sudo zfs set primarycache=metadata tank/backups
cr0x@server:~$ zfs get -o name,property,value primarycache tank/backups
NAME          PROPERTY     VALUE
tank/backups  primarycache metadata

Interpretación: Para destinos de backup que son mayormente write-once/read-rarely o streaming, cachear solo metadatos evita que ARC se contamine con datos grandes y de baja reutilización.
Esta sola propiedad ha salvado más máquinas de carga mixta que muchas “guías de rendimiento”.

Tarea 12: Observar I/O y latencia dentro del pool ZFS

cr0x@server:~$ zpool iostat -v 1 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        4.20T  3.05T  1.20K   650    140M   62.0M
  raidz2-0  4.20T  3.05T  1.20K   650    140M   62.0M
    sda         -      -   310    160    36.0M  15.0M
    sdb         -      -   290    170    34.0M  15.5M
    sdc         -      -   300    160    35.0M  15.0M
    sdd         -      -   300    160    35.0M  15.0M

Interpretación: Esto te da visibilidad a nivel de pool. Si las lecturas son altas y la tasa de misses de ARC es alta, probablemente estás limitado por disco.
Si las lecturas son altas pero los discos no lo reflejan, podrías estar rebotando entre capas de caché o ser limitado en otra parte.

Tarea 13: Detectar writeback sucio y throttling (Linux VM)

cr0x@server:~$ sysctl vm.dirty_background_ratio vm.dirty_ratio vm.dirty_writeback_centisecs vm.dirty_expire_centisecs
vm.dirty_background_ratio = 10
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000

Interpretación: Estos afectan cuándo el kernel inicia writeback en segundo plano y cuándo fuerza a los procesos a escribir.
En sistemas ZFS, estás equilibrando también el comportamiento de TXG de ZFS, así que los cambios aquí deben probarse cuidadosamente. Si ves picos periódicos de latencia de escritura, esto es sospechoso.

Tarea 14: Validar si una carga es streaming o reutiliza (prueba de utilidad de caché)

cr0x@server:~$ sudo perf stat -e minor-faults,major-faults,cache-misses -a -- sleep 10
 Performance counter stats for 'system wide':

       482,120      minor-faults
         2,104      major-faults
    21,884,110      cache-misses

      10.002312911 seconds time elapsed

Interpretación: Los major faults indican misses de la caché de páginas que requirieron I/O a disco. Un pico durante un job sugiere que la caché de páginas no está ayudando (o está siendo recuperada).
Esto no aísla ARC vs caché de páginas por sí solo, pero señala si el sistema está faulting repetidamente datos a memoria.

Playbook de diagnóstico rápido

Cuando el rendimiento cae y todos tienen una teoría, necesitas una secuencia corta que converja rápido. Este es el orden que uso en incidentes reales porque distingue “el disco está lento” de “la memoria está peleando” en minutos.

Paso 1: ¿Estamos no saludables o en reconstrucción?

Comprueba primero el estado del pool y el trabajo en segundo plano. Si estás haciendo scrub/resilver, no estás diagnosticando un sistema limpio.

cr0x@server:~$ zpool status
cr0x@server:~$ zpool iostat -v 1 5

Decide: Si hay resilver/scrub activo y la latencia es la queja, considera reprogramar o limitar antes de tocar perillas de ARC/caché de páginas.

Paso 2: ¿Es latencia de disco o presión de memoria?

cr0x@server:~$ iostat -x 1 5
cr0x@server:~$ cat /proc/pressure/memory
cr0x@server:~$ vmstat 1 5

Decide:
Si los awaits de disco son altos y la util está alta, estás limitado por I/O. Si PSI memoria es alto y disco no lo está, estás limitado por memoria/reclaim.
Si ambos son altos, puede haber un bucle de retroalimentación: el reclaim provoca I/O, que provoca stalls, que provoca más reclaim.

Paso 3: ¿ARC está sobredimensionado o mal aplicado?

cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c|c_min|c_max|memory_throttle_count)\s'
cr0x@server:~$ arcstat 1 10

Decide: Si ARC está cerca del máximo y hay presión de memoria, limita ARC o restringe el caching en datasets de streaming (primarycache=metadata) para detener la contaminación de caché.

Paso 4: ¿La carga es fundamentalmente cacheable?

cr0x@server:~$ arcstat 1 10
cr0x@server:~$ zpool iostat -v 1 10

Decide: Si la tasa de misses de ARC permanece alta mientras el throughput es grande y la reutilización es baja, deja de intentar “ganar” con cachés. Enfócate en throughput de disco, recordsize y programación.

Paso 5: Comprobar propiedades del dataset y desajuste con la aplicación

cr0x@server:~$ zfs get -s local,default recordsize,atime,compression,primarycache tank/data
cr0x@server:~$ ps -eo pid,cmd,%mem --sort=-%mem | head

Decide: Si una base de datos está en un dataset con recordsize enorme y caching “all”, podrías estar amplificando lecturas aleatorias y contaminando ARC.
Corregir esto suele ser más impactante que microgestionar parámetros de ARC.

Errores comunes, síntomas, soluciones

Error 1: Tratar la tasa de aciertos de ARC como la única verdad

Síntomas: El equipo celebra un 95% de aciertos mientras los usuarios aún ven picos de latencia; o entras en pánico con 20% de aciertos en un job de backup.

Solución: Clasifica la carga: streaming vs reutilización. Empareja arcstat con latencia de disco (iostat) y presión de memoria (PSI). Una baja tasa de aciertos en lecturas streaming es normal; la alta latencia no lo es.

Error 2: Dejar que cargas streaming contaminen ARC

Síntomas: Durante backups o scans, ARC crece, las cargas interactivas se vuelven lentas, y la caché “parece inútil” después.

Solución: Pon datasets de streaming/backup en primarycache=metadata (o incluso none en casos extremos). Considera pools separados si la contención es crónica.

Error 3: Limitar ARC a ciegas y llamarlo “tuneado”

Síntomas: Tras reducir ARC, cargas intensivas en metadatos se ralentizan dramáticamente; los discos se vuelven más activos; sube el uso de CPU.

Solución: Limita ARC con intención: deja margen para apps y caché de páginas, pero no tan bajo que ZFS pierda el conjunto de metadatos caliente. Valida con arcstat y latencia end-to-end.

Error 4: Suponer que L2ARC es gratuito

Síntomas: L2ARC mejora benchmarks sintéticos, pero la producción se vuelve con picos; aumenta la presión de memoria; el dispositivo de caché muestra actividad constante.

Solución: Asegura que la carga tenga reutilización. Mide antes/después con percentiles de latencia y lecturas de disco. Si domina el churn, elimina L2ARC y gasta presupuesto en RAM o mejor almacenamiento primario.

Error 5: Confundir SLOG/ZIL con caching de lectura

Síntomas: Compras un SLOG rápido esperando que las lecturas se aceleren; nada cambia; declaras que ZFS es “lento”.

Solución: Usa SLOG para mejorar la latencia de escrituras síncronas donde corresponda. Para lecturas, enfócate en ARC/L2ARC, recordsize y latencia de dispositivos.

Error 6: Ignorar señales de presión de memoria del kernel

Síntomas: Stalls periódicos, actividad de kswapd, OOM kills ocasionales, pero “memoria disponible” parece estar bien.

Solución: Usa PSI (/proc/pressure/memory), vmstat y logs para OOM/reclaim. Limita ARC, arregla procesos descontrolados y revisa límites de memoria de cgroups si hay contenedores involucrados.

Listas de verificación / plan paso a paso

Checklist A: Nuevo host ZFS-on-Linux (cargas mixtas)

  1. Decide tu presupuesto de memoria. ¿Cuánta RAM debe reservarse para aplicaciones y cuánta puede darse al cacheo del sistema de archivos?
    Si no puedes responder, estás delegando la arquitectura a heurísticas por defecto.
  2. Establece un tope inicial para ARC (conservador, ajusta después). Verifícalo tras el reinicio vía /proc/spl/kstat/zfs/arcstats.
  3. Clasifica datasets por patrón de acceso: interactivo, base de datos, backup/streaming, imágenes VM. Ajusta primarycache según corresponda.
  4. Fija recordsize por dataset según la carga (grande para archivos secuenciales, más pequeño para patrones aleatorios tipo DB).
  5. Establece un paquete de evidencia base: free, meminfo, PSI, arcstat, iostat -x, zpool iostat, y percentiles de latencia de la app.

Checklist B: Cuando alguien dice “ZFS se está comiendo toda mi RAM”

  1. Revisa PSI memoria y actividad de swap. Si no hay presión, ARC no es el villano—es tu RAM sin usar haciendo trabajo útil.
  2. Confirma tamaño de ARC vs max y si ARC se reduce cuando cambia la carga.
  3. Identifica la carga que contamina (a menudo backups, scans o analytics). Aplica primarycache=metadata a ese dataset.
  4. Si la presión persiste, limita ARC. Luego valida que las cargas clave no empeoraron por misses de metadatos.

Checklist C: Regresión de rendimiento tras un cambio

  1. Verifica salud del pool, estado de scrub/resilver y errores de dispositivo.
  2. Compara latencia de disco (iostat -x) antes/después. Si la latencia aumentó, no discutas sobre cachés todavía.
  3. Compara presión de memoria (PSI) antes/después. Cambios de kernel pueden desplazar comportamiento de reclaim/writeback.
  4. Compara comportamiento de ARC (tamaño, objetivo, misses). Si ARC está estable pero la app es más lenta, mira arriba (CPU, locks, configuración de la app) o abajo (dispositivos).

Preguntas frecuentes

1) ¿ARC es simplemente “la caché de páginas de ZFS”?

No. ARC cachea buffers de ZFS (datos y metadatos) dentro de la pila ZFS. La caché de páginas de Linux cachea páginas de archivos al nivel VFS.
Pueden solaparse, pero no son la misma capa ni el mismo motor de políticas.

2) ¿Por qué Linux muestra “casi nada de memoria libre” en una máquina ZFS sana?

Porque la RAM está para usarse. ARC y la caché de páginas usarán memoria para reducir I/O futuro.
La métrica que importa es si el sistema puede satisfacer asignaciones sin bloquearse o hacer swap—usa “available”, PSI y latencia observada.

3) ¿Debería siempre capar ARC en Linux?

En appliances de almacenamiento dedicados, a menudo dejas ARC grande. En servidores de uso mixto (bases de datos, contenedores, JVMs, build agents), un tope suele ser prudente.
El tope correcto depende de la carga: deja suficiente para apps y la VM, pero reserva bastante ARC para cachear metadatos y bloques calientes.

4) ¿Agregar más RAM siempre vence a añadir L2ARC?

A menudo, sí. La RAM reduce latencia y complejidad y ayuda tanto a ARC como al resto del sistema.
L2ARC puede ayudar cuando el conjunto de trabajo es mayor que la RAM y tiene reutilización, pero añade sobrecarga y no arregla cargas con mucho churn.

5) Si mi base de datos usa direct I/O, ¿ARC sigue importando?

Puede. Incluso si las lecturas de datos de usuario evitan algunos caminos de caché, los metadatos de ZFS siguen importando, y ZFS sigue gestionando I/O de bloques, checksums y layout.
Además, no todos los patrones de acceso DB son puro direct I/O todo el tiempo; y tareas en segundo plano pueden golpear el sistema de archivos de forma cacheable.

6) ¿Cuál es la forma más rápida de saber si estoy limitado por I/O o por presión de memoria?

Mira iostat -x para await/util del dispositivo y PSI (/proc/pressure/memory) junto con vmstat para reclaim/swap.
Await/util altos del disco sugieren I/O bound; PSI memoria alto sugiere presión de reclaim. Si ambos son altos, sospecha un bucle de retroalimentación.

7) ¿Cuándo debo poner primarycache=metadata?

Cuando el dataset sirve mayormente lecturas/escrituras en streaming (backups, archivos multimedia, logs fríos) y cachear datos de archivo en ARC desplazaría cargas más calientes.
Es especialmente útil en sistemas multi-tenant donde un job “leer todo una vez” puede expulsar los bloques calientes de los demás.

8) ¿Por qué mis benchmarks se ven increíbles después de la primera ejecución?

Porque las cachés se calentaron. Eso puede ser la caché de páginas de Linux, ARC, o ambas. La segunda ejecución a menudo mide velocidad de memoria, no del almacenamiento.
Si intentas medir almacenamiento, diseña el benchmark para controlar efectos de caché en lugar de pretender que no existen.

9) ¿Puedo “soltar cachés” con seguridad para probar?

Puedes soltar la caché de páginas de Linux, pero hacerlo en un sistema en producción es disruptivo y generalmente mala idea.
Además, soltar cachés de Linux no necesariamente reinicia ARC de la misma manera; puede que sigas midiendo comportamiento calentado de ZFS. Prefiere hosts de prueba controlados o cargas sintéticas con metodología clara.

10) ¿Cuál es la mejor métrica única para monitorizar a largo plazo?

Para la experiencia de usuario: percentiles de latencia a nivel de aplicación. Para salud del sistema: PSI de memoria y latencia de disco.
Las estadísticas de ARC son útiles, pero son evidencia de apoyo, no el titular.

Conclusión

ZFS ARC y la caché de páginas de Linux no son competidores en un sentido simplista; son sistemas de caching construidos en diferentes capas, con supuestos distintos y modos de fallo distintos.
ARC es brillante cacheando el mundo de ZFS—bloques, metadatos y la maquinaria que hace que snapshots y checksums se sientan rápidos. La caché de páginas es el amplificador de rendimiento predeterminado del kernel Linux, diseñada para ser recuperable y ampliamente útil.

Lo que debería preocuparte no es la pureza ideológica (“ZFS debería encargarse” vs “Linux debería encargarse”), sino la estabilidad operativa ante cambios.
Si ejecutas cargas mixtas, deja espacio libre, evita la contaminación de caché, mide presión en lugar de “memoria libre” y afina con evidencia en vez de folclore.
Así es como ganas la guerra de cachés: no convirtiéndola en una lucha.

← Anterior
Errores de Docker containerd/runc: cómo depurar sin reinstalar
Siguiente →
HDR en PC: por qué es asombroso… y por qué a veces apesta

Deja un comentario