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.

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.