Selección y Ajuste del Programador de E/S

Los programadores de E/S determinan cómo el kernel de Linux encola y envía solicitudes de almacenamiento a unidades. Seleccionar y ajustar el programador apropiado impacta significativamente el rendimiento de throughput, latencia y equidad. Los dispositivos de estado sólido modernos y NVMe tienen programadores óptimos diferentes que los discos giratorios tradicionales. Esta guía cubre selección de programador, parámetros de ajuste y estrategias de optimización de rendimiento.

Tabla de Contenidos

  1. Descripción General del Programador de E/S
  2. Programadores Disponibles
  3. Selección de Programador
  4. Parámetros Ajustables
  5. Ajuste de SSD vs HDD
  6. Benchmarking de Rendimiento
  7. Monitoreo de E/S
  8. Conclusión

Descripción General del Programador de E/S

Entender Programación de E/S

Los programadores de E/S optimizan el manejo de solicitudes de almacenamiento por:

  • Reordenar solicitudes para eficiencia mecánica
  • Fusionar operaciones de E/S adyacentes
  • Prevenir inanición de solicitud
  • Equilibrar throughput y latencia

Diferentes cargas de trabajo requieren diferentes programadores:

  • Base de datos: Baja latencia crítica
  • Streaming: Optimización de throughput
  • Multimedia: Equidad e interactividad

Programadores Disponibles

Programadores de Linux Modernos

# Listar programadores disponibles
cat /sys/block/sda/queue/scheduler

# Ejemplo de salida:
# noop [deadline] cfq

# Verificar programador actual
cat /sys/block/nvme0n1/queue/scheduler

# Programadores disponibles:
# - noop: No-op (omitir programación, para almacenamiento rápido)
# - deadline: Prioridad en solicitudes de lectura, equidad
# - cfq: Completely Fair Queuing (equidad, rendimiento interactivo)
# - mq-deadline: Multi-queue deadline (predeterminado moderno)
# - bfq: Budget Fair Queuing (equidad con alto throughput)
# - kyber: Optimizado para latencia (predeterminado NVMe)

Características del Programador

# noop: Sobrecarga mínima, confía en inteligencia de unidad
# - Mejor para: NVMe, SSDs de alta velocidad
# - Pros: Baja latencia, CPU mínima
# - Contras: Sin optimización

# deadline: Previene inanición, prioriza lecturas
# - Mejor para: Discos giratorios tradicionales
# - Pros: Justo, latencia predecible
# - Contras: Throughput menor que CFQ

# cfq: Distribución justa, rendimiento interactivo
# - Mejor para: Sistemas de propósito general
# - Pros: Justo, buena interactividad
# - Contras: Varianza de latencia

# mq-deadline: Versión multi-queue moderna de deadline
# - Mejor para: Sistemas modernos con muchas CPUs
# - Pros: Escalable, justo
# - Contras: Ninguno para la mayoría de cargas de trabajo

# bfq: Ancho de banda y equidad
# - Mejor para: Cargas de trabajo de escritorio/interactivas
# - Pros: Excelente equidad y capacidad de respuesta
# - Contras: CPU ligeramente más alta

# kyber: Optimizado para latencia
# - Mejor para: Dispositivos NVMe
# - Pros: Objetivo de latencia baja
# - Contras: No de propósito general

Selección de Programador

Cambiar Programador Dinámicamente

# Verificar programador actual
cat /sys/block/sda/queue/scheduler

# Cambiar programador en tiempo de ejecución
echo "deadline" | sudo tee /sys/block/sda/queue/scheduler

# Verificar cambio
cat /sys/block/sda/queue/scheduler

# Cambiar para múltiples dispositivos
for device in /sys/block/sd*/queue/scheduler; do
  echo "mq-deadline" | sudo tee $device
done

# Cambiar para NVMe
echo "noop" | sudo tee /sys/block/nvme0n1/queue/scheduler

Configuración Persistente de Programador

# Método 1: Parámetro de línea de comandos del kernel
sudo nano /etc/default/grub

# Agregar o modificar GRUB_CMDLINE_LINUX:
GRUB_CMDLINE_LINUX="... elevator=mq-deadline"

# Actualizar GRUB y reiniciar
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo reboot

# Método 2: Reglas de udev (persistente sin reinicio)
cat > /etc/udev/rules.d/60-scheduler.rules <<'EOF'
# Establecer programador para SSD
ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="noop"
# Establecer programador para HDD
ACTION=="add|change", KERNEL=="sd*", ATTR{queue/scheduler}="mq-deadline"
# Establecer programador para dispositivos virtuales
ACTION=="add|change", KERNEL=="vd*", ATTR{queue/scheduler}="mq-deadline"
EOF

# Recargar reglas de udev
sudo udevadm control --reload
sudo udevadm trigger

Parámetros Ajustables

Ajuste de Programador deadline

# Ver parámetros de deadline
ls -la /sys/block/sda/queue/iosched/

# Expiración de lectura (por defecto 500ms)
# Después de este tiempo, solicitudes de lectura obtienen prioridad
cat /sys/block/sda/queue/iosched/read_expire
echo 250 | sudo tee /sys/block/sda/queue/iosched/read_expire

# Expiración de escritura (por defecto 5000ms, 10x lectura)
cat /sys/block/sda/queue/iosched/write_expire
echo 2500 | sudo tee /sys/block/sda/queue/iosched/write_expire

# Prioridad de inanición de escritura
cat /sys/block/sda/queue/iosched/writes_starved
echo 2 | sudo tee /sys/block/sda/queue/iosched/writes_starved  # Menor = escrituras obtienen prioridad antes

Ajuste de Programador CFQ

# Ver parámetros de CFQ
ls -la /sys/block/sda/queue/iosched/

# Cuanto de tiempo (por defecto 64ms por proceso)
cat /sys/block/sda/queue/iosched/time_quantum
echo 32 | sudo tee /sys/block/sda/queue/iosched/time_quantum

# Tasas fifo (por defecto 2 async por sync)
cat /sys/block/sda/queue/iosched/fifo_expire_async

# Slice idle (optimización de búsqueda, por defecto 8ms)
cat /sys/block/sda/queue/iosched/slice_idle
echo 0 | sudo tee /sys/block/sda/queue/iosched/slice_idle  # Deshabilitar para cargas de trabajo de lote

Ajuste de Programador BFQ

# Ver parámetros de BFQ
ls /sys/block/sda/queue/iosched/

# Presupuesto máximo por grupo de solicitud
cat /sys/block/sda/queue/iosched/max_budget

# Cuanto de tiempo por grupo
cat /sys/block/sda/queue/iosched/time_quantum

# Optimizar para latencia
echo 1 | sudo tee /sys/block/sda/queue/iosched/low_latency

Ajuste de SSD vs HDD

Optimización de SSD

# Los SSDs se benefician de programación mínima
# Selector: mq-deadline o noop
echo "mq-deadline" | sudo tee /sys/block/nvme0n1/queue/scheduler

# Deshabilitar configuraciones de medios rotacionales
cat /sys/block/nvme0n1/queue/rotational
# Debe ser 0 para SSDs (usualmente automático)

# Habilitar NCQ (Native Command Queuing)
cat /sys/block/sda/device/queue_depth
# Aumentar si es posible para su dispositivo

# Deshabilitar fusión de E/S (los SSDs manejan esto eficientemente)
echo 2 | sudo tee /sys/block/nvme0n1/queue/nomerges

Optimización de HDD

# Los HDDs se benefician de programación más agresiva
echo "mq-deadline" | sudo tee /sys/block/sda/queue/scheduler

# Verificar detección de medios rotacionales
cat /sys/block/sda/queue/rotational
# Debe ser 1 para HDDs

# Aumentar anticipación de lectura
echo 500 | sudo tee /sys/block/sda/queue/iosched/read_expire

# Ajustado para patrones de acceso secuencial
cat /sys/block/sda/queue/iosched/slice_async_rq

Benchmarking de Rendimiento

Comparación de Rendimiento de Programador

# Preparar archivo de prueba
dd if=/dev/zero of=/tmp/test.img bs=1M count=10000

# Benchmark con diferentes programadores
for scheduler in noop deadline mq-deadline bfq; do
  echo "=== Testing $scheduler ==="
  echo $scheduler | sudo tee /sys/block/sda/queue/scheduler
  
  # Calentar caché
  cat /tmp/test.img > /dev/null
  
  # Lectura secuencial
  time dd if=/tmp/test.img of=/dev/null bs=4M
  
  # Lectura aleatoria
  fio --filename=/tmp/test.img --rw=randread --bs=4k \
    --iodepth=32 --runtime=30 --name=test
done

Pruebas de Carga de Trabajo de Base de Datos

# Benchmark de pgbench con diferentes programadores
for scheduler in deadline mq-deadline bfq; do
  echo "=== Testing $scheduler ==="
  echo $scheduler | sudo tee /sys/block/sdb/queue/scheduler
  
  # Inicializar base de datos
  pgbench -i -s 100 test_db
  
  # Ejecutar benchmark
  pgbench -c 20 -j 4 -T 60 test_db | grep "tps ="
done

Monitoreo de E/S

Estadísticas de E/S

# Monitorear E/S de dispositivo
iostat -x 1

# Campos a observar:
# - r/s: Solicitudes de lectura por segundo
# - w/s: Solicitudes de escritura por segundo
# - rrqm/s: Solicitudes de lectura fusionadas
# - wrqm/s: Solicitudes de escritura fusionadas
# - svctm: Tiempo de servicio
# - %util: Utilización de dispositivo

# Actividad de E/S por proceso
pidstat -d 1

# Resumen de E/S en todo el sistema
iotop -b -n 1

# Trazado de eventos de dispositivo de bloque
blktrace /dev/sda
# Analizar resultados
blkparse /dev/sda > trace.txt

Métricas de Programador

# Verificar longitud de cola de programador
watch -n 1 'cat /sys/block/sda/queue/iosched/pending'

# Monitorear envío de solicitudes
cat /sys/block/sda/queue/iosched/dispatched

# Verificar actividad de fusión
cat /sys/block/sda/queue/iosched/merged

# Para programador deadline
watch -n 1 'cat /sys/block/sda/queue/iosched/*'

# Entender impacto de rendimiento
cat /proc/diskstats | grep sda

Conclusión

La selección y ajuste del programador de E/S impactan directamente el rendimiento de almacenamiento, afectando tanto throughput como latencia. Los sistemas modernos con NVMe y SSDs de alto rendimiento a menudo se benefician de sobrecarga de programación mínima, mientras que los discos giratorios tradicionales requieren optimización de solicitud más sofisticada. Al entender características de programador, parámetros de ajuste y requisitos específicos de carga de trabajo, los equipos de infraestructura optimizan rendimiento de almacenamiento sin cambios de código complejos. El benchmarking regular valida opciones de programador y efectividad de ajuste, asegurando que la infraestructura de almacenamiento entregue rendimiento óptimo para cargas de trabajo diversas.