Estados P y C: qué hace tu CPU cuando está inactiva

¿Te fue útil?

El informe de incidente siempre empieza igual: “La CPU estaba al 12% y aun así la latencia aumentó.”
Miras los paneles, ves margen libre, y alguien sugiere “quizá la base de datos está lenta.”
Mientras tanto, el verdadero culpable es más silencioso: la CPU está ahorrando energía tan agresivamente que despertarla te cuesta milisegundos que no habías presupuestado.

Los estados P y C son las perillas y engranajes detrás de la “inactividad”. También explican por qué un servidor puede estar “mayormente inactivo”
y aun así sentirse como si caminara por molasses cuando llega la siguiente ráfaga de trabajo. Si gestionas sistemas en producción,
no necesitas convertirte en un microarquitecto de CPU, pero sí necesitas la alfabetización operativa suficiente para no pisar minas.

Un modelo mental apto para producción: P-states vs C-states

Piensa en tu CPU como si tuviera dos tipos de “modos”:

  • P-states (estados de rendimiento): la CPU está ejecutando, pero en distintos puntos de frecuencia/voltaje.
    Un P-state de mayor rendimiento suele significar mayor frecuencia y mayor consumo. Un P-state bajo significa más lento pero más barato.
  • C-states (estados de inactividad): la CPU no ejecuta instrucciones útiles.
    Cuanto más profundo es el C-state, más partes del núcleo (y a veces del paquete completo) pueden apagarse, ahorrando energía—pero despertarlo tarda más.

Esa es la versión simple. La versión operativa añade dos notas al pie que deberías tatuar en tus runbooks:

  • Los P-states no son una perilla “configurar y olvidar”. El SO, el firmware y la propia CPU pueden influir en la selección de frecuencia.
    En sistemas Intel modernos, el hardware puede tomar gran parte de las decisiones incluso si crees que Linux manda.
  • Los C-states pueden ser por núcleo y por paquete. Un núcleo ruidoso vecino puede impedir que todo el socket alcance un sueño profundo de paquete.
    A la inversa, un sistema “silencioso” puede entrar tan profundo en sueño que la siguiente petición pague una penalización de despertado fea.

Un atajo mental más: los P-states tratan sobre “qué tan rápido mientras trabaja”. Los C-states tratan sobre “qué tan dormido mientras espera”.
La mayoría de incidentes ocurren cuando optimizas uno y te olvidas del otro.

Qué hace realmente la CPU cuando está “inactiva”

Cuando Linux no tiene nada ejecutable para una CPU, ejecuta un bucle de idle. El bucle de inactividad no es solo girar
(a menos que lo fuerces). Normalmente emite una instrucción como HLT (halt) o usa mecanismos más avanzados
que permiten a la CPU entrar en estados de sueño más profundos.

Estados C por núcleo: C0 hasta “lo suficientemente profundo como para molestarte”

C0 significa “activo”. Todo lo demás es alguna variante de “no ejecutar instrucciones”. El mapeo exacto difiere entre proveedores,
pero el patrón operativo es consistente:

  • C1: sueño ligero. Salida rápida. Ahorro de energía mínimo.
  • C1E: C1 mejorado; a menudo reduce el voltaje con más agresividad.
  • C3: sueño más profundo; más relojes internos desconectados; mayor latencia de salida.
  • C6/C7 y compañía: sueño muy profundo; puede vaciar cachés, apagar partes del núcleo; la latencia de salida puede ser apreciable.

La latencia de salida es el impuesto oculto. Si tu carga es explosiva y sensible a la latencia, los C-states profundos pueden convertir
“mayormente inactivo” en “periódicamente lento”.

Estados C de paquete: todo el socket hace la siesta

Los estados C de paquete (a menudo etiquetados PC2/PC3/PC6/PC10) son donde están los grandes ahorros de energía.
También son donde viven las sorpresas. El paquete solo puede profundizar si se cumplen condiciones:

  • Todos los núcleos están lo suficientemente inactivos.
  • Los componentes uncore (LLC, controlador de memoria, interconexión) pueden reducir reloj/potencia.
  • Los dispositivos y el firmware están de acuerdo en que es seguro.

En entornos de servidores, una única fuente de interrupciones ruidosa, el tick del temporizador o una política de energía mal configurada puede bloquear los estados profundos de paquete.
O al contrario: se permite un sueño profundo de paquete y tu latencia tail empieza a hacer malabarismos interpretativos.

P-states: la selección de frecuencia ya no es una sola perilla

La historia antigua era: el SO selecciona una frecuencia de una tabla; la CPU la usa. La historia moderna es: el SO establece políticas y sugerencias,
y la lógica interna de la CPU a menudo hace los bucles de control rápidos. El controlador intel_pstate de Intel, CPPC de AMD,
y los P-states gestionados por hardware difuminan la línea entre “gobernador” y “firmware”.

El turbo complica aún más las cosas. Turbo no es “una frecuencia”. Es un conjunto de comportamientos de impulso oportunista
limitados por energía, temperatura, corriente y cuántos núcleos están activos. Tu monitor puede decir “3.5 GHz”
mientras la CPU hace impulsos por núcleo que varían microsegundo a microsegundo.

Broma #1: Si alguna vez quieres sentirte impotente, intenta discutir con una CPU sobre lo que significa “frecuencia máxima”.

Por qué debes preocuparte: latencia, jitter, rendimiento y costes

Latencia y latencia tail

Los C-states profundos añaden latencia de despertado. La escalada de frecuencia añade latencia de rampa. Normalmente esto es de microsegundos a milisegundos bajos,
lo que suena pequeño hasta que estás ejecutando:

  • Servicios RPC con SLO estrictos (p99 importa, no la media)
  • backends de almacenamiento donde el tiempo de finalización de IO es visible para el usuario
  • bases de datos con contención de bloqueos donde pequeños retrasos se magnifican
  • sistemas de trading de baja latencia donde el jitter es un riesgo profesional

En otras palabras: si tu sistema está “inactivo la mayor parte del tiempo” pero debe responder rápido cuando no lo está, debes preocuparte.

Rendimiento sostenido y throughput

Los P-states y el turbo deciden cuánta carga haces por vatio. Pero el turbo está limitado por umbrales de energía (PL1/PL2 en Intel),
térmica y restricciones de plataforma. Si fuerzas “modo rendimiento” en todas partes, podrías ganar en pruebas cortas y perder rendimiento sostenido
porque alcanzas límites de energía/temperatura y te estrangulan fuerte.

Consumo, refrigeración y dinero real

Si operas a escala, la política de energía de la CPU cambia la historia del centro de datos: electricidad, refrigeración y densidad por rack.
Incluso si no pagas la factura de energía directamente, la pagarás en planificación de capacidad.

Aquí la verdad cínica de SRE: no puedes gastar tu camino fuera del jitter de latencia si la configuración de tu flota es inconsistente.
Y no puedes afinar tu camino fuera de un presupuesto energético si tu aplicación está girando sin hacer nada.

Datos interesantes y breve historia (porque este lío tiene raíces)

  • ACPI estandarizó los estados de energía para que los sistemas operativos gestionaran energía entre distintos fabricantes en lugar de interfaces BIOS a medida.
  • Las CPUs de la era “SpeedStep” pusieron la escalada de frecuencia en el mainstream; antes de eso, “gestión de energía” era sobre todo “apagar la pantalla”.
  • El comportamiento turbo moderno está limitado por energía, no por frecuencia: las CPUs persiguen envolventes de energía y temperatura, no un reloj fijo.
  • Los C-states son anteriores a la nube, pero la nube volvió dolorosos sus trade-offs: las cargas multiinquilino son explosivas e impredecibles.
  • Los kernels sin tick (NO_HZ) redujeron las interrupciones periódicas del temporizador para que las CPUs pudieran permanecer inactivas más tiempo y alcanzar C-states más profundos.
  • Intel introdujo control P-state gestionado por hardware para reaccionar más rápido que el bucle del planificador del SO.
  • RAPL (Running Average Power Limit) dio a software una forma de medir/limitar energía de CPU, convirtiendo la energía en métrica de primera clase.
  • Los C-states de paquete se volvieron importantes a medida que la potencia del uncore (LLC, controlador de memoria, interconexión) rivalizaba con la del núcleo.
  • La virtualización complicó todo: la “inactividad” de un guest no es necesariamente inactividad del host; halting en una VM implica política del hipervisor.

Cómo controla Linux los P-states y C-states

El plano de control: drivers, gobernadores y políticas

En Linux, la escalada de frecuencia de CPU suele gestionarse por el subsistema cpufreq. Dos controladores comunes que verás:

  • intel_pstate (Intel): a menudo el predeterminado en Intel modernos. Puede operar en “modo activo” donde la CPU participa mucho en las decisiones.
  • acpi-cpufreq: controlador ACPI más tradicional con tablas de frecuencias explícitas.

Los gobernadores son políticas como performance, powersave, y (según el driver) schedutil.
No trates los nombres de gobernador como verdades universales; su comportamiento puede variar según el controlador.

El plano de inactividad: cpuidle, controladores C-state y restricciones de latencia

Los C-states en Linux se gestionan por el subsistema cpuidle. Selecciona un estado de inactividad basado en:

  • duración prevista de inactividad (cuánto tiempo hasta que un evento despierte la CPU)
  • latencia de salida de cada estado de inactividad
  • restricciones QoS (pistas de sensibilidad a latencia del kernel/usuarios)
  • lo que la plataforma y el firmware permiten

BIOS/UEFI: el lugar donde “solo cambiaremos una opción” se convierte en folklore

Las configuraciones de firmware pueden sobrescribir o restringir todo:

  • Máximo C-state permitido (por ejemplo, limitar a C1)
  • Límites de C-state de paquete
  • Habilitar/deshabilitar turbo
  • Energy/Performance Bias (EPB de Intel)
  • “Perfiles de energía” del proveedor que hacen varias cosas a la vez

En producción, el modo de fallo más común no es “kernel equivocado”. Es “valores predeterminados de BIOS diferentes entre lotes”.

Una cita sobre fiabilidad (idea parafraseada)

Idea parafraseada atribuida a John Ousterhout: la complejidad es la causa raíz de muchos problemas de fiabilidad.
La gestión de energía es complejidad con un vatímetro.

Tareas prácticas: comandos, significado de salidas y decisiones

El único ajuste que importa es el ajuste que puedes verificar. A continuación están las tareas reales que espero que un ingeniero on-call ejecute,
con comandos, salidas de ejemplo y qué decisión tomar a partir de ellas.

Tarea 1: Identificar el driver de frecuencia activo y los gobernadores

cr0x@server:~$ cpupower frequency-info
analyzing CPU 0:
  driver: intel_pstate
  CPUs which run at the same hardware frequency: 0
  available cpufreq governors: performance powersave
  current policy: frequency should be within 800 MHz and 3900 MHz.
                  The governor "powersave" may decide which speed to use
  current CPU frequency: 1200 MHz (asserted by call to hardware)
  boost state support:
    Supported: yes
    Active: yes

Qué significa: Estás usando intel_pstate; las opciones de gobernador son limitadas y el comportamiento es específico del driver.
La frecuencia actual es baja porque la política lo permite. El turbo está habilitado.

Decisión: Si estás diagnosticando picos de latencia, ten en cuenta que powersave bajo intel_pstate aún puede impulsar,
pero las características de rampa difieren. No cambies gobernadores a ciegas; mide primero.

Tarea 2: Comprobar política de frecuencia mínima/máxima por CPU

cr0x@server:~$ for f in /sys/devices/system/cpu/cpu*/cpufreq/scaling_{min,max}_freq; do echo "$f: $(cat $f)"; done | head
/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq: 800000
/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq: 3900000
/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq: 800000
/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq: 3900000

Qué significa: Los límites de política del SO son amplios. Si el rendimiento sigue siendo pobre, la limitación está en otra parte
(límites de energía, térmica, C-states, contención).

Decisión: Si scaling_max_freq está inesperadamente bajo, sospecha un perfil de afinamiento, restricciones del runtime de contenedores,
o eventos de límite de potencia de la plataforma.

Tarea 3: Inspeccionar estado de turbo/boost

cr0x@server:~$ cat /sys/devices/system/cpu/cpufreq/boost
1

Qué significa: Turbo/boost está habilitado.

Decisión: Para servicios sensibles a latencia, el turbo suele ayudar (tiempo de servicio más rápido).
Para latencia determinista, el turbo puede añadir variabilidad térmica; considera bloquear la política solo tras medir.

Tarea 4: Verificar disponibilidad y residencia de estados de inactividad de CPU (C-states por núcleo)

cr0x@server:~$ sudo cpupower idle-info
CPUidle driver: intel_idle
CPUidle governor: menu
analyzing CPU 0:
  Number of idle states: 4
  Available idle states: POLL C1 C1E C6
  C1: exit latency 2 us
  C1E: exit latency 10 us
  C6: exit latency 85 us

Qué significa: Existe un C6 profundo con ~85 µs de latencia de salida (ejemplo). No es catastrófico, pero no es gratis.

Decisión: Si tus p99 se correlacionan con periodos de inactividad, considera limitar el C-state más profundo solo en nodos afectados y vuelve a probar.

Tarea 5: Comprobar tiempo por estado y contadores de uso de estados de inactividad

cr0x@server:~$ for s in /sys/devices/system/cpu/cpu0/cpuidle/state*; do \
  echo "$(basename $s) name=$(cat $s/name) disable=$(cat $s/disable) time=$(cat $s/time) usage=$(cat $s/usage)"; \
done
state0 name=POLL disable=0 time=122 usage=18
state1 name=C1 disable=0 time=983421 usage=24011
state2 name=C1E disable=0 time=221934 usage=9120
state3 name=C6 disable=0 time=55290321 usage=110432

Qué significa: CPU0 pasa mucho tiempo en C6. Eso es bueno para la energía. Puede ser malo para la latencia de despertado.

Decisión: Si ves latencia tail, este es candidato principal. A continuación, correlaciona con métricas de la aplicación e interrupciones.

Tarea 6: Comprobar residencia de C-state de paquete (Intel, vía turbostat)

cr0x@server:~$ sudo turbostat --Summary --quiet --show PkgWatt,PkgTmp,Pkg%pc2,Pkg%pc6,Pkg%pc10 --interval 1 --num_iterations 3
PkgWatt  PkgTmp  Pkg%pc2  Pkg%pc6  Pkg%pc10
  32.15     54      2.12     8.41     61.77
  28.02     52      1.88     7.96     68.10
  35.44     55      2.30     9.02     58.33

Qué significa: El paquete frecuentemente alcanza PC10 (sueño profundo). Potencia baja. Excelente para eficiencia.
También causa clásico “cold-start latency” al despertar.

Decisión: Si ejecutas cargas de baja latencia, considera limitar los C-states de paquete o usar un perfil tuned de baja latencia en esos nodos.
Si ejecutas trabajos por lotes, celebra y sigue adelante.

Tarea 7: Buscar señales de límite de potencia y throttling (Intel RAPL / térmica)

cr0x@server:~$ sudo turbostat --quiet --show Bzy_MHz,Avg_MHz,Busy%,CoreTmp,PkgTmp,PkgWatt,CorWatt,GFXWatt --interval 1 --num_iterations 2
Bzy_MHz  Avg_MHz  Busy%  CoreTmp  PkgTmp  PkgWatt  CorWatt  GFXWatt
   4200     1850  22.15       72      79    165.2     92.1     0.0
   4100     1902  23.40       74      81    165.0     93.0     0.0

Qué significa: Existen clocks de boost, pero la potencia del paquete es alta. Si las temperaturas suben, puedes estrangular pronto.

Decisión: Si el rendimiento es inconsistente bajo carga, inspecciona refrigeración, límites de potencia y comportamiento sostenido de turbo antes de culpar al kernel.

Tarea 8: Confirmar modo de tick del kernel y comportamiento de temporizadores (disrupción de inactividad)

cr0x@server:~$ grep -E 'NO_HZ|CONFIG_HZ' -n /boot/config-$(uname -r) | head -n 5
114:CONFIG_HZ=250
501:CONFIG_NO_HZ_COMMON=y
504:CONFIG_NO_HZ_IDLE=y
507:CONFIG_NO_HZ_FULL is not set

Qué significa: El idle sin ticks está activado (NO_HZ_IDLE), lo que ayuda a los C-states profundos. No es totalmente sin ticks.

Decisión: Si tu carga necesita latencia consistente baja, puedes preferir menos transiciones profundas de inactividad (política), no necesariamente cambiar la configuración del kernel.

Tarea 9: Identificar hotspots de interrupciones que impiden inactividad o causan tormentas de wake

cr0x@server:~$ sudo cat /proc/interrupts | head -n 15
           CPU0       CPU1       CPU2       CPU3
  0:         21         18         19         22   IO-APIC   2-edge      timer
  1:          0          0          0          0   IO-APIC   1-edge      i8042
 24:     883421     102331      99321      90122   PCI-MSI  327680-edge  eth0-TxRx-0
 25:     112331     843221     121112     110998   PCI-MSI  327681-edge  eth0-TxRx-1

Qué significa: Las colas de NIC están pesadas en ciertas CPUs. Esto puede impedir que los núcleos entren en inactividad y también causar despertados explosivos.

Decisión: Considera ajustar la afinidad de IRQ (o el comportamiento de irqbalance) si ves hotspots en un solo núcleo o picos de latencia alineados a interrupciones.

Tarea 10: Comprobar el estado de irqbalance y si está luchando con tu afinamiento

cr0x@server:~$ systemctl status irqbalance --no-pager
● irqbalance.service - irqbalance daemon
     Loaded: loaded (/lib/systemd/system/irqbalance.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-01-10 08:21:10 UTC; 2h 12min ago
       Docs: man:irqbalance(1)
   Main PID: 912 (irqbalance)

Qué significa: irqbalance está activo. Buen valor por defecto—a menos que hagas pinning manual de IRQs para baja latencia y olvides desactivarlo.

Decisión: Si necesitas aislamiento estricto de CPU, configura irqbalance con CPUs prohibidas o desactívalo y gestiona afinidades explícitamente.

Tarea 11: Ver si un perfil tuned está imponiendo ahorro agresivo de energía

cr0x@server:~$ tuned-adm active
Current active profile: virtual-guest

Qué significa: Un perfil tuned está activo, potencialmente alterando el gobernador de CPU y otros parámetros relevantes para latencia.

Decisión: Para un host de base de datos o servicio RPC sensible a latencia, prueba latency-performance (o el perfil recomendado por el proveedor) en un nodo canario.

Tarea 12: Ver rápidamente el gobernador actual en todas las CPUs

cr0x@server:~$ grep -H . /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2>/dev/null | head
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor:powersave
/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor:powersave
/sys/devices/system/cpu/cpu2/cpufreq/scaling_governor:powersave
/sys/devices/system/cpu/cpu3/cpufreq/scaling_governor:powersave

Qué significa: Todas las CPUs están en powersave.

Decisión: Si persigues regresiones de latencia, cambia un host a performance temporalmente y mide p99. No lo apliques a toda la flota por corazonadas.

Tarea 13: Cambiar temporalmente el gobernador (y entender el riesgo)

cr0x@server:~$ sudo cpupower frequency-set -g performance
Setting cpu: 0
Setting cpu: 1
Setting cpu: 2
Setting cpu: 3

Qué significa: Has solicitado el gobernador de rendimiento. En intel_pstate, esto cambia el comportamiento de la política, no fija un reloj.

Decisión: Usa esto como experimento controlado. Si la latencia mejora materialmente y el presupuesto de energía lo permite, considera un perfil tuned en lugar de cambios ad-hoc.

Tarea 14: Limitar el C-state más profundo (prueba quirúrgica, no modo de vida)

cr0x@server:~$ echo 1 | sudo tee /sys/devices/system/cpu/cpu0/cpuidle/state3/disable
1

Qué significa: Has deshabilitado un estado de inactividad (aquí, state3 podría ser C6). Esto fuerza un sueño más superficial en CPU0.

Decisión: Si p99 mejora y el consumo sube aceptablemente, aplícalo mediante un método persistente (args del kernel, tuned, o unidad systemd) y documéntalo.

Tarea 15: Comprobar efectos de virtualización: ¿estás afinando al invitado mientras el host decide?

cr0x@server:~$ systemd-detect-virt
kvm

Qué significa: Estás dentro de una VM. Los controles de energía del invitado pueden tener efecto limitado; la política del host y el planificador del hipervisor importan más.

Decisión: Si necesitas comportamiento de baja latencia, trabaja con el equipo de plataforma: pinning de CPU, gobernador del host y política de C-states son las palancas reales.

Tarea 16: Comprobar presión de CPU y contención en el scheduling (porque “inactivo” puede ser mentira)

cr0x@server:~$ cat /proc/pressure/cpu
some avg10=0.00 avg60=0.10 avg300=0.08 total=18873412
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

Qué significa: La presión de CPU es baja; el planificador no está luchando. Si la latencia es mala, céntrate en el comportamiento de wake/sleep, interrupciones, IO o contención de locks.

Decisión: Si some o full está alto, no persigas primero los C-states—arregla la contención, límites de CPU o vecinos ruidosos.

Guía rápida de diagnóstico

Este es el orden que uso cuando alguien dice “la latencia sube cuando la máquina está mayormente inactiva” o “la CPU está baja pero las cosas van lentas.”
Está optimizado para encontrar el cuello de botella rápido, no para hacerte sentir ingenioso.

Primero: decide si persigues comportamiento de energía de la CPU o otra cosa

  1. Comprobar presión de CPU (contención del planificador):
    si PSI está alto, no estás “inactivo”, estás sobresuscrito o estrangulado.
  2. Comprobar cola de ejecución y tiempo de steal (especialmente en VMs):
    baja utilización puede coexistir con alta latencia si estás esperando ser programado.
  3. Comprobar iowait y latencia de almacenamiento:
    mucha “CPU inactiva” en realidad es “bloqueado en IO”.

Segundo: confirma qué política de energía está activa

  1. Driver + gobernador vía cpupower frequency-info.
  2. ¿Turbo activado? vía /sys/devices/system/cpu/cpufreq/boost.
  3. Perfil tuned o servicio del proveedor que imponga política.

Tercero: mide residencia de C-states y perturbaciones de wake

  1. Uso/tiempo de C-states de núcleo vía /sys/.../cpuidle o cpupower idle-info.
  2. C-states de paquete vía turbostat (si está disponible).
  3. Hotspots de interrupciones vía /proc/interrupts y herramientas de afinidad IRQ.

Haz un cambio a la vez, en un nodo, con un temporizador

La forma más rápida de perder una semana es alternar ajustes de BIOS, parámetros del kernel y perfiles tuned en la misma ventana de mantenimiento.
Cambia una cosa, mide p95/p99 y potencia/térmicas, luego decide.

Tres micro-historias del mundo corporativo

Micro-historia 1: El incidente causado por una suposición equivocada

Un equipo desplegó una nueva pasarela API interna “ligera”. Era eficiente: CPU baja, ráfagas cortas, mucho uso de interrupciones de red.
En los paneles, la CPU rondaba 15–25%. Todos se felicitaron por no sobredimensionar.
Luego la latencia p99 se duplicó fuera de horas pico, justo cuando el tráfico se calmó.

La primera suposición fue clásica: “menos carga significa más margen”. Pero el servicio era explosivo.
Durante periodos tranquilos, las CPUs entraban en C-states profundos de paquete. Cuando llegaba la siguiente ráfaga, el manejo de peticiones pagaba latencia de despertado
más latencia de rampa de frecuencia. Individualmente pequeño, colectivamente feo.

La segunda suposición: “Estamos en governor performance, así que la frecuencia es alta.” No lo estaban.
La mitad de la flota tenía un perfil de BIOS diferente. Esos hosts permitían estados de paquete más profundos y tenían una política más sesgada a la energía.
La flota era heterogénea y el balanceador mezclaba hosts con distintos comportamientos de wake.

La solución no fue heroica. Estandarizaron perfiles de firmware, luego probaron en canario un perfil tuned de baja latencia solo en nodos de gateway.
Mantuvieron el sueño profundo habilitado para workers por lotes. La latencia se estabilizó, la energía siguió razonable, y el incidente acabó con una breve lista de verificación añadida al aprovisionamiento.

Micro-historia 2: La optimización que salió mal

Un equipo de almacenamiento quería reducir consumo. Forzaron C-states más profundos y pusieron gobernadores en powersave en nodos de almacenamiento.
En teoría era responsable: los nodos esperaban mucho IO y las CPUs no parecían ocupadas.

Lo que no vieron fue cómo se comporta el almacenamiento bajo cargas mixtas. Las rutas de finalización de IO son sensibles a latencia y están impulsadas por interrupciones.
El servicio permanecía quieto y de repente procesaba una tormenta de finalizaciones, trabajo de checksum y respuestas de red.
Con C-states profundos, la latencia del manejador desde la interrupción creció. Con escalado agresivo de frecuencia, los núcleos empezaban lentos y luego subían.

El contratiempo mostró un síntoma extraño: la latencia promedio seguía aceptable, pero la latencia tail y el jitter se volvieron brutales.
Los clientes reintentaron. Los reintentos causaron microráfagas. Las microráfagas hicieron que las CPUs rebotaran entre sueño y despertar aún más.
El cambio “ahorro de energía” creó un bucle que desperdició tanto energía como tiempo.

Revirtieron en los frontends de almacenamiento pero mantuvieron el ahorro en nodos de compactación en background.
La lección real fue el alcance: la política de energía es específica por carga. Aplícala por rol, no por cluster, y siempre vigila p99 y tasas de reintento.

Micro-historia 3: La práctica aburrida pero correcta que salvó el día

Otra compañía ejecutaba una flota Kubernetes con generaciones mixtas de instancias. Su equipo de plataforma hizo algo profundamente no sexy:
mantuvieron una matriz de capacidades hardware y una prueba de aprovisionamiento que registraba disponibilidad de C-states, estado de turbo y residencia de inactividad.
Cada nueva actualización de BIOS tenía que pasar las mismas pruebas antes de entrar en la imagen dorada.

Un trimestre, una actualización de firmware del proveedor cambió los límites predeterminados de C-state de paquete.
Nada explotó inmediatamente. Ese es el truco—este tipo de cambio no siempre rompe las cosas ruidosamente. Solo altera las características de latencia.

Sus pruebas lo detectaron porque la residencia de C-states de paquete registrada cambió significativamente en nodos inactivos.
No necesitaron que un cliente se quejara primero. Pausaron el despliegue, ajustaron la política de firmware y documentaron la diferencia.

El resultado fue aburrido: ningún incidente. El equipo de plataforma no recibió elogios.
Pero los equipos de aplicación nunca tuvieron que aprender sobre C-states de paquete a las 3 a.m., que es la forma más alta de éxito operativo.

Broma #2: El mejor cambio en gestión de energía es el que nunca aparece en una diapositiva de postmortem.

Errores comunes (síntomas → causa raíz → solución)

1) “La CPU está baja pero la latencia p99 es alta”

Síntomas: baja utilización promedio de CPU; grandes picos de latencia tail durante periodos tranquilos; mejor latencia bajo carga sostenida.

Causa raíz: C-states profundos y/o escalado de frecuencia agresivo causan penalizaciones de despertado y rampa; el tráfico explosivo desencadena transiciones repetidas.

Solución: mide residencia de C-states (núcleo y paquete). Prueba en canario un perfil de baja latencia o limita los C-states más profundos en nodos afectados.
Confirma la consistencia de perfiles de BIOS en la flota.

2) “Frecuencia atrapada baja incluso bajo carga”

Síntomas: cpupower frequency-info muestra frecuencia actual baja; rendimiento por debajo de lo esperado; temperaturas moderadas.

Causa raíz: scaling_max_freq limitado por política, interacciones con cuota de CPU en contenedores, o límites de potencia de la plataforma.

Solución: comprueba scaling_max_freq y perfil tuned; confirma turbo; inspecciona límites de potencia/throttling con turbostat.
En contenedores, verifica cuota de CPU y asignaciones de cpuset.

3) “El rendimiento mejoró en un nodo pero no en otro”

Síntomas: mismo software, latencia distinta; cambios de afinamiento funcionan de forma inconsistente entre hosts.

Causa raíz: valores predeterminados de firmware heterogéneos, diferencias de microcódigo, o distintos drivers de frecuencia (intel_pstate vs acpi-cpufreq).

Solución: estandariza configuraciones de BIOS; asegura parámetros del kernel consistentes; inventaría selección de driver y versiones de microcódigo.

4) “Tormentas de IRQ impiden inactividad y desperdician energía”

Síntomas: el paquete nunca alcanza C-states profundos; vatios en inactividad más altos; ciertas CPUs muestran conteos enormes de interrupciones.

Causa raíz: desequilibrio de afinidad de interrupciones, colas NIC mal configuradas, dispositivos ruidosos o comportamiento del temporizador.

Solución: inspecciona /proc/interrupts; ajusta afinidad de IRQ; configura correctamente el número de colas; revisa la configuración de irqbalance.

5) “Deshabilitamos C-states y ahora el throughput empeoró”

Síntomas: aumento del consumo; aparece throttling térmico; rendimiento sostenido baja después de un pequeño pico inicial.

Causa raíz: eliminar ahorros de inactividad eleva temperatura/potencia base, reduciendo cabeza de turbo y provocando estrangulamiento.

Solución: no deshabilites estados profundos indiscriminadamente. Usa políticas por rol. Monitoriza térmicas y potencia de paquete; busca estabilidad, no relojes máximos.

6) “Hemos fijado CPUs, pero la latencia aún jitterea”

Síntomas: aislamiento de CPU configurado; aún ves jitter; colas largas ocasionales.

Causa raíz: la gestión de energía aún hace transiciones de núcleo/paquete; interrupciones caen sobre CPUs aisladas; contención entre siblings de SMT.

Solución: alinea afinidad de IRQ con aislamiento; considera limitar C-states profundos para núcleos aislados; revisa la política SMT para cargas críticas de latencia.

Listas de verificación / plan paso a paso

Checklist A: Estandarizar una línea base de energía para la flota (la parte aburrida que previene sorpresas)

  1. Inventaria modelos de CPU, versiones de microcódigo y estado de virtualización en los nodos.
  2. Registra el driver de frecuencia (intel_pstate/acpi-cpufreq) y gobernadores en la gestión de configuración.
  3. Registra ajustes de perfil de BIOS/UEFI (límites C-state, turbo, EPB) por generación de hardware.
  4. Define políticas por rol: crítico-latencia, equilibrado, batch/eficiencia.
  5. Aplica perfiles tuned o equivalentes vía automatización; no hagas ajustes manuales aislados.
  6. Muestra continuamente la residencia de C-states de paquete y vatios en canarios inactivos para detectar desviaciones tras actualizaciones de firmware.

Checklist B: Afinar un nodo de servicio sensible a latencia (de forma segura)

  1. Base: captura p95/p99 de latencia, tasa de errores/reintentos y consumo en reposo y bajo ráfaga típica.
  2. Confirma que no es contención de CPU: revisa PSI CPU y colas de ejecución.
  3. Mide residencia de C-states de paquete en reposo y durante ráfagas.
  4. Cambio en canario: cambia el perfil tuned o gobernador en un nodo.
  5. Si sigue habiendo picos, prueba limitar el C-state más profundo (temporal) y vuelve a medir.
  6. Valida térmicas y límites de potencia sostenida; vigila estrangulamiento.
  7. Despliega por rol, no por flota. Documenta la política con “por qué”, no solo “qué”.

Checklist C: Afinar un nodo batch orientado a eficiencia

  1. Confirma que la carga prioriza throughput y tolera jitter.
  2. Habilita/permite C-states de paquete profundos y gobernadores balanceados.
  3. Vigila tormentas de interrupciones que mantengan el paquete despierto (vatios desperdiciados).
  4. Monitorea energía por trabajo (o por GB procesado), no solo tiempo de ejecución.

Preguntas frecuentes

1) ¿Los P-states y C-states son independientes?

Mayormente, pero no totalmente. Los C-states gobiernan qué pasa en inactividad; los P-states gobiernan rendimiento activo.
En la práctica interactúan vía térmicas y límites de potencia: un inactivo profundo puede mejorar la cabeza de turbo, y deshabilitar inactividad puede reducir impulso sostenido.

2) ¿Debería usar siempre el gobernador performance en servidores?

No. Para frontends sensibles a latencia puede ayudar. Para flotas batch suele ser un desperdicio.
Además, en intel_pstate, performance no significa “reloj máximo fijo”. Significa una política más agresiva.
Toma decisiones por rol y mide p99 y vatios.

3) Si los C-states añaden latencia, ¿por qué no deshabilitarlos en todas partes?

Porque lo pagarás en consumo, calor y a veces en throttling—además de menor cabeza de turbo.
Deshabilitar C-states profundos puede ser una herramienta dirigida para roles específicos. Rara vez es buen predeterminado para toda la flota.

4) ¿Por qué la latencia mejora bajo carga sostenida?

Bajo carga sostenida, los núcleos permanecen en C0 y las frecuencias se estabilizan en niveles más altos. Evitas costos de despertado y rampa.
Las cargas explosivas pagan esos costos repetidamente, y la latencia tail sufre.

5) ¿Cómo sé si el SO o el hardware controla la frecuencia?

Empieza con cpupower frequency-info para ver el driver. En Intel moderno, intel_pstate en modo activo significa que el hardware juega un rol importante.
También fíjate si la frecuencia actual aparece con “asserted by call to hardware” en la salida.

6) ¿La virtualización cambia la historia?

Sí. La inactividad de un guest está mediada por el hipervisor. La frecuencia y el sueño profundo de paquete suelen estar controlados por el host.
Si ajustas dentro de una VM y no ves resultados, no es mala suerte; es que no manejas las palancas correctas.

7) ¿Cuál es la diferencia operativa entre C-states por núcleo y por paquete?

Los C-states por núcleo afectan la profundidad de sueño y latencia de despertado de un solo núcleo. Los estados de paquete afectan componentes a nivel socket y pueden ahorrar mucha más energía.
Los estados de paquete también pueden causar penalizaciones más notables en la “primera petición después de inactividad”, según la plataforma.

8) ¿Puede el afinamiento de interrupciones arreglar latencia relacionada con C-states?

A veces. Si las interrupciones despiertan constantemente núcleos inactivos, verás desperdicio de energía y jitter.
Si las interrupciones se concentran en pocas CPUs, esas CPUs pueden nunca dormir mientras otras van profundo, creando comportamiento de respuesta desigual.
Balancear o fijar interrupciones correctamente puede estabilizar la latencia.

9) ¿Cómo decido entre modos “baja latencia” y “energía eficiente”?

Usa el SLO y el modelo de costes de la carga. Si tienes objetivos p99 estrictos y tráfico explosivo, sesga hacia baja latencia en esos nodos.
Si tienes trabajos batch o colas elásticas, sesga hacia eficiencia. Evita mezclar políticas en el mismo pool detrás de un balanceador.

10) ¿Cuál es el primer experimento seguro si sospecho de C-states?

Canarya un solo nodo: captura la línea base, luego cambia a un perfil tuned de baja latencia o limita temporalmente el estado de inactividad más profundo.
Si p99 mejora sin provocar throttling o aumento inaceptable de consumo, has probado la causalidad.

Conclusión: pasos prácticos siguientes

“Inactivo” no es un estado neutral. Es una decisión de política activa tomada por capas de silicio, firmware y código del kernel—cada una intentando ahorrar energía,
ocasionalmente robándote presupuesto de latencia en el proceso.

Pasos siguientes que realmente aguantan en producción:

  1. Mide antes de afinar: recoge driver/gobernador, residencia de C-states y latencia p95/p99 en un nodo canario.
  2. Estandariza la política de firmware: los valores predeterminados de BIOS inconsistentes son un asesino silencioso de flotas.
  3. Separa por rol: nodos de baja latencia y nodos eficientes no deben compartir la misma política de energía.
  4. Haz los cambios reversibles: toggles mediante perfiles tuned o gestión de configuración, no sesiones SSH artesanales.
  5. Vigila la latencia tail y reintentos: las medias te mentirán con toda tranquilidad.
← Anterior
Caché de CPU (L1/L2/L3) en términos sencillos: por qué la memoria gana
Siguiente →
NTP entre oficinas: la pequeña cosa que rompe AD, VPN y certificados

Deja un comentario