Gestión de Memoria y Optimización de Swap
La gestión de memoria impacta fundamentalmente el rendimiento del sistema, con políticas de memoria ineficientes causando thrashing, picos de latencia y rendimiento reducido. Linux proporciona controles sofisticados de gestión de memoria incluyendo ajuste de swappiness, políticas de caché de página y configuración de swap. Esta guía cubre optimización de utilización de memoria para patrones de carga de trabajo específicos y evitar problemas comunes de gestión de memoria.
Tabla de Contenidos
- Fundamentos de Gestión de Memoria
- Configuración de Swappiness
- Ajuste de Caché de Página
- Configuración del Asesino de OOM
- Gestión de Archivo de Swap
- zswap y Swap Comprimido
- Páginas Enormes
- Monitoreo de Memoria
- Conclusión
Fundamentos de Gestión de Memoria
Jerarquía de Memoria
# Jerarquía de asignación de memoria de Linux:
# 1. Caché de página (archivos accedidos recientemente)
# 2. Memoria de aplicación (heap, stack)
# 3. Swap (desbordamiento basado en disco)
# Ver uso actual de memoria
free -h
# Desglose detallado de memoria
cat /proc/meminfo | head -20
# Memoria por proceso
ps aux | head -5
# RSS: Resident Set Size (RAM actual usado)
# VSZ: Tamaño de memoria virtual (asignado pero no todo en RAM)
Presión de Memoria
# Verificar métricas de presión de memoria
cat /proc/pressure/memory
# La salida muestra:
# some: Tiempo que tareas esperaron por memoria
# full: Tiempo que el sistema no podría asignar memoria
# Monitorear presión de memoria en tiempo real
watch -n 1 'cat /proc/pressure/memory'
Configuración de Swappiness
Entender Swappiness
# Valor actual de swappiness (0-100)
cat /proc/sys/vm/swappiness
# Valores más altos (por defecto 60):
# - Uso de swap más agresivo
# - Mejor para escritorio (respuesta interactiva)
# - Problemático para servidores (picos de latencia)
# Valores más bajos (0-30):
# - Mantener datos en RAM
# - Mejor para servidores y bases de datos
# - Puede golpear OOM más rápido
# Cero (no recomendado en kernels actuales):
# - Históricamente deshabilitaba swap
# - Causa muertes por OOM en lugar de degradación elegante
Ajuste de Swappiness
# Verificar swappiness actual
sysctl vm.swappiness
# Ajustar swappiness para cargas de trabajo de servidor
sudo sysctl -w vm.swappiness=10
# Más agresivo para bases de datos que necesitan RAM
sudo sysctl -w vm.swappiness=5
# Caso extremo (solo emergencia)
sudo sysctl -w vm.swappiness=1
# Verificar cambios
sysctl vm.swappiness
# Hacer persistente
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.d/99-memory-tuning.conf
sudo sysctl -p /etc/sysctl.d/99-memory-tuning.conf
Swappiness en la Práctica
# Monitorear uso de swap con diferentes configuraciones de swappiness
watch -n 1 'free -h && echo "---" && cat /proc/sys/vm/swappiness'
# Identificar presión de swap
grep Swap /proc/meminfo
# Verificar actividad de E/S de swap
vmstat 1
# Observar fallos de página aumentados
grep pgfault /proc/stat
# Detectar thrashing de swap
watch -n 1 'grep -E "pswpin|pswpout" /proc/vmstat'
Ajuste de Caché de Página
Presión de Caché
# Ver presión actual de caché
cat /proc/sys/vm/cache_pressure
# Por defecto 100: Comportamiento de caché normal
# 0-50: Aumentar retención de caché
# 100: Comportamiento equilibrado
# 200+: Descartar caché agresivamente
# Aumentar retención de caché para cargas de trabajo que se benefician del almacenamiento en caché
sudo sysctl -w vm.cache_pressure=50
# Descartar caché agresivamente para cargas de trabajo de working-set
sudo sysctl -w vm.cache_pressure=200
# Ajuste específico de aplicación
# Base de datos con gran pool de búfer: presión de caché más baja
# Streaming de alto rendimiento: presión de caché más alta
Comportamiento de Reclamación de Memoria
# Comportamiento de descarga de caché de archivo
cat /proc/sys/vm/dirty_ratio # Porcentaje de memoria para vaciar
cat /proc/sys/vm/dirty_background_ratio
# Aumentar relación dirty para escrituras de alto throughput
sudo sysctl -w vm.dirty_ratio=20 # Por defecto 20%
sudo sysctl -w vm.dirty_background_ratio=5 # Por defecto 10%
# Reducir para sensibilidad en tiempo real
sudo sysctl -w vm.dirty_ratio=5
sudo sysctl -w vm.dirty_background_ratio=2
# Timeout para páginas dirty (centisegundos)
cat /proc/sys/vm/dirty_expire_centisecs # Por defecto 3000 = 30 segundos
Configuración del Asesino de OOM
Entender el Asesino de OOM
# El asesino de OOM se activa cuando memoria completamente agotada
# Selecciona y mata el proceso para liberar memoria
# Monitorear eventos de OOM
dmesg | grep -i "out of memory"
# Verificar registros del sistema
journalctl -u kernel --grep="OOM"
# Estado actual del asesino de OOM
sysctl vm.oom_dump_tasks
# Pánico en OOM (reinicio del sistema en lugar de matar)
sudo sysctl -w vm.panic_on_oom=1
Ajuste de Puntuación de OOM de Proceso
# Ver puntuación de OOM de proceso
cat /proc/*/oom_score | sort -n | tail -5
# Puntuación de OOM más baja = menos probable ser matado
# Puede ser negativa (0-15)
# Ajustar para proceso específico
echo -500 > /proc/$(pgrep mysql)/oom_score_adj
# Deshabilitar asesino de OOM para proceso crítico
echo -1000 > /proc/$(pgrep critical_app)/oom_score_adj
# Hacer proceso más fácil de matar (limpieza de emergencia)
echo 500 > /proc/$(pgrep cleanup_worker)/oom_score_adj
# Puntuación de OOM persistente vía systemd
# Agregar a archivo de servicio:
# OOMScoreAdjust=-500
Gestión de Archivo de Swap
Crear Archivos de Swap
# Verificar swap actual
swapon --show
# Crear archivo de swap
sudo dd if=/dev/zero of=/swapfile bs=1G count=4
# Asegurar archivo de swap (solo root)
sudo chmod 600 /swapfile
# Formatear como swap
sudo mkswap /swapfile
# Habilitar swap
sudo swapon /swapfile
# Verificar
swapon --show
# Habilitar al arranque (agregar a /etc/fstab)
echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab
# Verificar sintaxis de fstab
sudo mount -a
Prioridad de Swap
# Verificar prioridades de swap
swapon --show
# Agregar segundo swap con prioridad
sudo swapon --priority 10 /swapfile2
# O vía fstab (la prioridad es opción)
# /swapfile none swap sw,priority=10 0 0
# Prioridad más alta: usado primero
# Prioridad más baja: usado como desbordamiento
# Monitorear selección de swap
watch -n 1 'grep -E "pswpin|pswpout" /proc/vmstat'
zswap y Swap Comprimido
Configuración de zswap
# Verificar disponibilidad de zswap
grep -i zswap /boot/config-$(uname -r)
# Cargar módulo zswap
sudo modprobe zswap
# Configurar parámetros de zswap
sudo sysctl -w vm.zswap.enabled=1
# Tamaño de pool de memoria zswap (por defecto 20% de RAM)
cat /sys/module/zswap/parameters/max_pool_percent
echo 30 | sudo tee /sys/module/zswap/parameters/max_pool_percent
# Algoritmo de compresión (por defecto lzo)
cat /sys/module/zswap/parameters/compressor
# Opciones: lzo, lz4, zstd (si se compila)
# Pool de compresión (por defecto z3fold)
cat /sys/module/zswap/parameters/zpool
zswap vs Swap Físico
# Ventajas de zswap:
# - Memoria comprimida en RAM (compresión típica de 2-4x)
# - Más rápido que swap de disco
# - Reduce E/S de swap
# Desventajas:
# - Usa CPU para compresión
# - Reduce memoria de aplicación disponible
# - No adecuado para intercambiar cantidades masivas
# Enfoque híbrido:
# - Habilitar zswap para desbordamiento de ráfaga
# - Tener swap de disco para desbordamiento sostenido
# - Equilibra latencia y capacidad
Páginas Enormes
Habilitar Páginas Enormes
# Verificar configuración de página enorme
cat /proc/meminfo | grep -i huge
# Verificar tamaños de página enormes disponibles
grep . /sys/kernel/mm/hugepages/*/nr_hugepages
# Asignar páginas enormes de 2MB
echo 512 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# Asignar páginas enormes de 1GB
echo 4 | sudo tee /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
# Configuración persistente vía sysctl
echo "vm.nr_hugepages=512" | sudo tee -a /etc/sysctl.d/hugepages.conf
sudo sysctl -p /etc/sysctl.d/hugepages.conf
Soporte de Páginas Enormes de Aplicación
# Base de datos (MongoDB/Redis) con páginas enormes
# Usualmente requiere configuración explícita:
# Configuración de Redis
# En redis.conf:
# config set maxmemory-policy noeviction
# Iniciar con páginas enormes
sudo numactl --cpunodebind=0 --membind=0 redis-server --maxmemory 16gb
# Monitorear uso de página enorme
watch -n 1 'cat /proc/meminfo | grep Huge'
Monitoreo de Memoria
Monitoreo de Memoria en Tiempo Real
# Uso general de memoria
free -h
# Desglose detallado de memoria
cat /proc/meminfo
# Información de presión de stall de memoria
watch -n 1 'cat /proc/pressure/memory'
# Memoria por proceso
ps aux --sort=-%mem | head -10
# Estadísticas de memoria virtual
vmstat 1
# Fallos de página e intercambio
watch -n 1 'grep -E "pgfault|pswpin|pswpout" /proc/vmstat'
Perfilado de Memoria
# Monitorear memoria de proceso específico
watch -n 1 'ps aux | grep mysql'
# Mapa de memoria detallado del proceso
cat /proc/$(pgrep mysql)/maps | head -20
# Uso de memoria por biblioteca
cat /proc/$(pgrep mysql)/smaps | grep -i "Size"
# Estadísticas de caché
cat /proc/meminfo | grep -E "Buffers|Cached"
# Porcentaje de memoria libre
free | awk '/Mem/ {printf "%.2f%% free\n", $NF/$2 * 100}'
Conclusión
La gestión de memoria de Linux impacta directamente la estabilidad del sistema, latencia y throughput. Al ajustar swappiness, gestionar swap apropiadamente, configurar páginas enormes y entender el comportamiento de OOM, los equipos de infraestructura previenen degradación de rendimiento y aseguran comportamiento del sistema predecible. Diferentes cargas de trabajo requieren diferentes políticas de memoria; la optimización requiere entender requisitos de aplicación específicos y monitorear comportamiento bajo carga realista. Combinado con ajuste de E/S de almacenamiento y optimización de CPU, la optimización de gestión de memoria crea la base para infraestructura de alto rendimiento.


