Swappiness 180: el valor que hace funcionar zram (y la regla udev que te lo estaba impidiendo)
TL;DR: Crea /etc/sysctl.d/99-vm-zram-parameters.conf con vm.swappiness = 180 y los otros 3 parámetros. Luego busca si tu distro tiene reglas udev o archivos sysctl que lo sobrescriban — ese fue mi problema.
Si solo quieres que funcione, copia estos comandos:
sudo tee /etc/sysctl.d/99-vm-zram-parameters.conf << 'EOF'
vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0
EOF
sudo sysctl --system
Luego verifica: cat /proc/sys/vm/swappiness debe mostrar 180. Si muestra otro valor, sigue leyendo — tienes un conflicto.
Configurar zram no sirve de nada si el kernel no lo usa. Y eso es exactamente lo que pasa con swappiness=10: el kernel evita swap hasta que la RAM está casi agotada. Con zram (swap en RAM), eso es contradictorio.
Qué es swappiness
vm.swappiness controla la agresividad del kernel al mover páginas de RAM a swap. Los valores van de 0 a 200:
- 0 = nunca swapear si no es absolutamente necesario
- 60 = valor por defecto de Linux
- 10 = lo que muchas distros ponen para SSD (evita desgaste)
- 180 = lo que Pop!_OS recomienda para zram
La intuición normal es “swappiness bajo = mejor rendimiento”. Y eso es verdad con swap en disco, porque escribir en disco es lento. Pero zram no es disco — es RAM comprimida. Comprimir y descomprimir en RAM es órdenes de magnitud más rápido que I/O de disco.
La documentación del kernel lo dice claro:
“For in-memory swap, like zram or zswap, values beyond 100 can be considered. For example, if the random IO against the swap device is on average 2x faster than IO from the filesystem, swappiness should be 133.”
zram es probablemente 100x más rápido que un SSD. Así que 180 es conservador.
Qué pasa en la práctica:
- Con swappiness=10: el kernel espera a que la RAM esté casi llena. zram se usa como último recurso.
- Con swappiness=180: el kernel mueve páginas inactivas a zram ANTES. zram funciona como extensión natural de la memoria.
Los 4 parámetros sysctl para zram
# /etc/sysctl.d/99-vm-zram-parameters.conf
vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0
vm.watermark_scale_factor: detección temprana de presión
El kernel usa “watermarks” (marcas de agua) para decidir cuándo empieza a liberar memoria:
- high — todo bien, no hacer nada
- low — empezar a liberar memoria (kswapd se activa)
- min — pánico, liberar memoria YA
El valor por defecto es 10 — las marcas están tan juntas que el kernel solo reacciona cuando ya casi no queda memoria.
Con valor 125, las marcas están más separadas. El kernel detecta presión antes y libera gradualmente.
vm.page-cluster: leer swap en bloques
Controla cuántas páginas swap se leen a la vez (potencias de 2). Por defecto es 3 → 8 páginas a la vez.
En disco, leer bloques es eficiente (I/O secuencial). Pero en zram (RAM), el acceso aleatorio es instantáneo — no hay beneficio en agrupar. Peor aún: agrupar desperdicia memoria si solo necesitas una de las 8 páginas.
Valor 0 es lo correcto para zram.
vm.watermark_boost_factor: por qué 0
Controla si el kernel “boostea” temporalmente las marcas de agua cuando detecta presión. Con valor 0, no lo hace. La razón: este boost puede causar micro-picos de presión que confunden a systemd-oomd y generan kills prematuros.
La regla de oro: sysctl y zram JUNTOS
swappiness=180 solo es seguro si zram es ram / 2 o menos. ¿Por qué?
Con zram de 30 GB y swappiness 180:
- El kernel swapea agresivamente a zram
- zram tiene 30 GB de capacidad
- zram consume ~15 GB de RAM física para comprimir
- Te quedan solo ~17 GB de RAM para procesos
- Un proceso crece y te quedas sin margen otra vez
Con zram de 16 GB y swappiness 180:
- El kernel swapea agresivamente a zram
- zram tiene 16 GB de capacidad
- zram consume ~8 GB de RAM física (ratio 2:1)
- Te quedan ~24 GB de RAM para procesos
- El sistema es estable
El enemigo oculto: la regla udev
Después de configurar swappiness=180, verifiqué con sysctl --system. Mostraba 180. Pero minutos después:
cat /proc/sys/vm/swappiness
# 10
Algo lo estaba reescribiendo. Busqué:
grep -r "swappiness" /usr/lib/udev/rules.d/ /etc/udev/rules.d/
Encontré dos cosas:
1. La regla udev de la distribución:
# /usr/lib/udev/rules.d/30-zram.rules
ACTION=="change", KERNEL=="zram0", ATTR{initstate}=="1", SYSCTL{vm.swappiness}="150"
Cada vez que zram0 cambia de estado, esta regla reescribe swappiness.
2. Nuestro override local (que teníamos mal):
# /etc/udev/rules.d/99-zram-local.rules
ACTION=="change", KERNEL=="zram0", ATTR{initstate}=="1", SYSCTL{vm.swappiness}="10"
Nosotros mismos habíamos creado un override que forzaba swappiness=10.
Y además había un archivo conflictivo:
# /etc/sysctl.d/99-swappiness.conf
vm.swappiness=10
Tres cosas sobrescribiendo el valor. La solución:
# 1. Desactivar el archivo conflictivo
sudo mv /etc/sysctl.d/99-swappiness.conf /etc/sysctl.d/99-swappiness.conf.disabled
# 2. Corregir la regla udev local
sudo sed -i 's/SYSCTL{vm.swappiness}="10"/SYSCTL{vm.swappiness}="180"/' \
/etc/udev/rules.d/99-zram-local.rules
# 3. Aplicar sin reboot
sudo sysctl --system
sudo udevadm trigger --action=change --sysname-match=zram0
Cómo buscar si tu distro tiene este problema
# Verificar valor real
cat /proc/sys/vm/swappiness
# Buscar reglas udev que sobrescriben
grep -r "swappiness" /usr/lib/udev/rules.d/ /etc/udev/rules.d/
# Buscar archivos sysctl conflictivos
grep -r "swappiness" /etc/sysctl.d/ /usr/lib/sysctl.d/
Si encuentras algo que no sea 180, tienes el mismo problema.
Cómo aplicarlo
1. Crear el archivo sysctl
sudo tee /etc/sysctl.d/99-vm-zram-parameters.conf << 'EOF'
vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0
EOF
2. Verificar que no hay conflictos
grep -r "swappiness" /etc/sysctl.d/ /usr/lib/sysctl.d/ /etc/udev/rules.d/ /usr/lib/udev/rules.d/
Si hay otros archivos con swappiness, desactívalos o corrígelos.
3. Reboot (junto con el cambio de zram)
Estos cambios deben aplicarse junto con la configuración de zram. Son interdependientes.
4. Verificar
cat /proc/sys/vm/swappiness
# Debe mostrar 180
sysctl vm.swappiness vm.page-cluster vm.watermark_scale_factor
# vm.swappiness = 180
# vm.page-cluster = 0
# vm.watermark_scale_factor = 125
Artículos de esta serie
- Cómo duplicar la RAM de tu Linux con zram y swap comprimida (sin comprar nada)
- zram: mitad de RAM, algoritmo zstd y por qué tu distro lo tiene mal configurado
- Swappiness 180: el valor que hace funcionar zram (y la regla udev que te lo estaba impidiendo) ← estás aquí
- RAM → zram → swap en disco: cómo montar un sistema de swap por capas y probarlo con stress-ng
- systemd-oomd y Docker limits: lo que nadie te cuenta para proteger tu sistema
Referencias
- Kernel docs — vm.swappiness — explicación oficial
- Pop!_OS zram tuning — los valores que usan y por qué
- ArchWiki — zram — la referencia canónica