P-states et C-states : ce que fait votre CPU lorsqu’il est inactif

Cet article vous a aidé ?

Le rapport d’incident commence toujours de la même manière : « Le CPU n’était qu’à 12 % et pourtant la latence a grimpé. »
Vous regardez les tableaux de bord, voyez beaucoup de marge, puis quelqu’un suggère « peut-être que la base de données est lente ».
Pendant ce temps, le vrai coupable est plus discret : le CPU économise de l’énergie si agressivement que le réveil vous coûte des millisecondes non budgétisées.

Les P-states et les C-states sont les boutons et les engrenages derrière « inactif ». Ce sont aussi la raison pour laquelle un serveur peut être « majoritairement inactif »
et pourtant donner l’impression d’avancer dans de la mélasse quand arrive la prochaine rafale de travail. Si vous exploitez des systèmes de production,
vous n’avez pas besoin de devenir microarchitecte CPU — mais il vous faut suffisamment de littératie opérationnelle pour éviter de marcher sur des mines.

Un modèle mental orienté production : P-states vs C-states

Pensez à votre CPU comme ayant deux sortes de « modes » :

  • P-states (états de performance) : le CPU est en fonctionnement, mais à différents points fréquence/tension.
    Un P-state de performance plus élevé implique généralement une fréquence et une consommation plus élevées. Un P-state plus bas signifie plus lent mais moins coûteux.
  • C-states (états d’inactivité) : le CPU n’exécute pas d’instructions utiles.
    Plus l’état C est profond, plus de parties du cœur (et parfois du package entier) peuvent être mis hors tension, économisant de l’énergie — mais le réveil prend plus de temps.

Voilà la version simple. La version opérationnelle ajoute deux notes que vous devriez tatouer dans vos runbooks :

  • Les P-states ne sont pas un bouton « régler et oublier ». Le système d’exploitation, le microcode et le CPU lui-même peuvent influencer la sélection de fréquence.
    Sur les systèmes Intel modernes, le matériel peut prendre beaucoup de décisions même si vous pensez que Linux est aux commandes.
  • Les C-states peuvent être par cœur et par package. Un seul cœur bruyant peut empêcher la prise d’un sommeil profond pour l’ensemble du socket.
    Inversement, un système « calme » peut entrer si profondément en sommeil que la requête suivante paie une pénalité de réveil désagréable.

Un raccourci mental supplémentaire : les P-states concernent « à quelle vitesse quand on travaille ». Les C-states concernent « à quel point endormi en attendant ».
La plupart des incidents surviennent lorsque vous optimisez l’un et oubliez l’autre.

Ce que le CPU fait réellement lorsqu’il est « inactif »

Quand Linux n’a rien d’exécutable pour un CPU, il lance une boucle idle. La boucle idle ne se contente pas de tourner
(sauf si vous la forcez). Elle émet typiquement une instruction comme HLT (halt) ou utilise des mécanismes plus avancés
qui permettent au CPU d’entrer dans des états de sommeil plus profonds.

États C du cœur : C0 jusqu’à « assez profond pour vous ennuyer »

C0 signifie « actif ». Tout le reste est une saveur de « n’exécute pas d’instructions ». Le mappage exact varie selon les fournisseurs,
mais le modèle opérationnel est cohérent :

  • C1 : sommeil léger. Sortie rapide. Économies d’énergie minimales.
  • C1E : C1 amélioré ; réduit souvent la tension plus agressivement.
  • C3 : sommeil plus profond ; plus d’horloges internes coupées ; latence de sortie plus élevée.
  • C6/C7 et apparentés : sommeil très profond ; peut vider des caches, mettre hors tension des parties du cœur ; la latence de sortie devient mesurable.

La latence de sortie est la taxe cachée. Si votre charge est en rafales et sensible à la latence, les C-states profonds peuvent transformer
« majoritairement inactif » en « périodiquement lent ».

États C du package : tout le socket fait la sieste

Les états C du package (souvent étiquetés PC2/PC3/PC6/PC10) contiennent les grandes économies d’énergie.
Ils contiennent aussi les surprises. Le package ne peut aller en profond que si certaines conditions sont remplies :

  • Tous les cœurs sont suffisamment inactifs.
  • Les composants uncore (LLC, contrôleur mémoire, interconnect) peuvent être mis en horloge/puissance réduite.
  • Les périphériques et le firmware conviennent que c’est sûr.

En environnement serveur, une seule source d’interruptions bavarde, un timer tick, ou une politique d’alimentation mal configurée peut bloquer les états package profonds.
Ou, à l’inverse : le sommeil package profond est autorisé, et votre latence de queue commence à faire des danses interprétatives.

P-states : la sélection de fréquence n’est plus un seul bouton

L’ancienne histoire disait : l’OS sélectionne une fréquence dans une table ; le CPU l’exécute. L’histoire moderne : l’OS définit des politiques et des indices,
et la logique interne du CPU réalise souvent des boucles de contrôle rapides. Le pilote intel_pstate d’Intel, le CPPC d’AMD,
et les P-states gérés par le matériel estompent la ligne entre « gouverneur » et « firmware ».

Le turbo complique encore les choses. Le turbo n’est pas « une fréquence ». C’est un ensemble de comportements de boost opportunistes
limités par la puissance, la température, le courant et le nombre de cœurs actifs. Votre monitoring peut indiquer « 3.5 GHz »
pendant que le CPU effectue des boosts par cœur qui varient microseconde après microseconde.

Blague n°1 : si vous voulez un jour vous sentir impuissant, essayez de discuter avec un CPU sur ce que signifie « fréquence maximale ».

Pourquoi vous devriez vous en préoccuper : latence, jitter, débit et coûts

Latence et latence de queue

Les C-states profonds ajoutent une latence de réveil. L’échelle de fréquence ajoute une latence de montée en puissance. Généralement, il s’agit de microsecondes à quelques millisecondes,
ce qui paraît faible jusqu’à ce que vous exécutiez :

  • des services RPC avec des SLO stricts (le p99 compte, pas la moyenne)
  • des backends de stockage où le temps de complétion IO est visible pour l’utilisateur
  • des bases de données avec contention sur des verrous où de petits délais s’amplifient
  • des systèmes de trading à faible latence où le jitter est un risque professionnel

En d’autres termes : si votre système est « inactif la plupart du temps » mais doit répondre rapidement quand il n’est pas inactif, vous devez vous en préoccuper.

Débit et performance soutenue

Les P-states et le turbo déterminent combien de travail vous effectuez par watt. Mais le turbo est borné par des limites de puissance (PL1/PL2 sur Intel),
la thermique et les contraintes de plateforme. Si vous forcez le « mode performance » partout, vous gagnerez peut-être des benchmarks courts mais perdrez en débit soutenu
car vous atteindrez des plafonds thermiques/power et serez fortement throttlés.

Puissance, refroidissement et argent réel

Si vous opérez à grande échelle, la politique de puissance CPU change l’histoire du datacenter : électricité, refroidissement et densité de racks.
Même si vous ne payez pas directement la facture d’électricité, vous la paierez lors de la planification de capacité.

Voici la vérité cynique SRE : vous ne pouvez pas dépenser pour résoudre le jitter de latence si la configuration de votre flotte est incohérente.
Et vous ne pouvez pas ajuster indéfiniment une politique d’alimentation si votre application tourne en rond à faire du CPU en attendant.

Faits intéressants et courte histoire (parce que ce bazar a des racines)

  • ACPI a standardisé les états d’alimentation pour que les systèmes d’exploitation puissent gérer l’énergie à travers les fournisseurs plutôt que des interfaces BIOS sur mesure.
  • Les CPU de l’ère « SpeedStep » ont rendu la mise à l’échelle des fréquences grand public ; avant cela, « gestion d’alimentation » signifiait surtout « éteindre l’écran ».
  • Le turbo moderne est limité par la puissance, pas par la fréquence : les CPU cherchent des enveloppes de puissance et thermique, pas un horloge fixe.
  • Les C-states précèdent le cloud, mais le cloud a rendu leurs compromis douloureux : les charges multi-tenant sont rafales et imprévisibles.
  • Les noyaux sans tick (NO_HZ) ont réduit les interruptions périodiques pour laisser les CPU inactifs plus longtemps et atteindre des C-states plus profonds.
  • Intel a introduit le contrôle P-state géré par le matériel pour réagir plus vite que la boucle du scheduler de l’OS.
  • RAPL (Running Average Power Limit) a donné aux logiciels un moyen de mesurer/limiter l’énergie CPU, faisant de la puissance une métrique de première classe.
  • Les C-states de package sont devenus critiques à mesure que la consommation uncore (LLC, contrôleur mémoire, interconnect) a commencé à rivaliser avec la consommation des cœurs.
  • La virtualisation a tout compliqué : l’« inactivité » d’un invité n’est pas nécessairement une inactivité hôte ; le halt dans une VM implique une politique d’hyperviseur.

Comment Linux contrôle les P-states et les C-states

Le plan de contrôle : pilotes, gouverneurs et politiques

Sous Linux, la mise à l’échelle de la fréquence CPU est généralement gérée par le sous-système cpufreq. Deux pilotes courants :

  • intel_pstate (Intel) : souvent le défaut sur les Intel modernes. Peut fonctionner en mode « actif » où le CPU participe fortement aux décisions.
  • acpi-cpufreq : pilote ACPI plus traditionnel avec des tables de fréquences explicites.

Les gouverneurs sont des politiques comme performance, powersave et (selon le pilote) schedutil.
Ne traitez pas les noms de gouverneurs comme des vérités universelles ; leur comportement varie selon le pilote.

Le plan d’inactivité : cpuidle, pilotes C-state et contraintes de latence

Les C-states sous Linux sont gérés par le sous-système cpuidle. Il choisit un état d’inactivité en fonction de :

  • la durée prédite d’inactivité (combien de temps avant le prochain événement qui réveille le CPU)
  • la latence de sortie de chaque état d’inactivité
  • les contraintes QoS (indices de sensibilité à la latence depuis le kernel/utilisateurspace)
  • ce que la plateforme et le firmware autorisent

BIOS/UEFI : l’endroit où « on changera juste un paramètre » devient une légende

Les réglages du firmware peuvent outrepasser ou contraindre tout le reste :

  • État C maximal autorisé (ex. limiter à C1)
  • Limites d’état C du package
  • Activation/désactivation du turbo
  • Energy/Performance Bias (EPB d’Intel)
  • « Profils d’alimentation » du fournisseur qui font plusieurs choses à la fois

En production, le mode d’échec le plus fréquent n’est pas « mauvais noyau ». C’est « valeurs par défaut BIOS différentes entre lots ».

Une citation fiabilité (idée paraphrasée)

Idée paraphrasée attribuée à John Ousterhout : la complexité est la cause première de nombreux problèmes de fiabilité.
La gestion d’alimentation, c’est de la complexité avec un wattmètre.

Tâches pratiques : commandes, sens des sorties et décisions

Le seul réglage qui compte est celui que vous pouvez vérifier. Ci-dessous des tâches réelles que j’attends d’un ingénieur en astreinte,
avec commandes, exemples de sorties et la décision à prendre.

Task 1: Identify the active CPU frequency driver and governors

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

Ce que cela signifie : Vous êtes sur intel_pstate ; les choix de gouverneur sont limités et le comportement dépend du pilote.
La fréquence actuelle est basse parce que la politique l’autorise. Le turbo est activé.

Décision : Si vous diagnostiquez des pics de latence, notez que powersave sous intel_pstate peut toujours booster,
mais les caractéristiques de montée en fréquence diffèrent. Ne changez pas de gouverneur à l’aveugle ; mesurez d’abord.

Task 2: Check min/max frequency policy per 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

Ce que cela signifie : Les bornes de politique OS sont larges. Si la performance est encore mauvaise, la limitation est ailleurs
(caps de puissance, thermique, états C, contention).

Décision : Si scaling_max_freq est anormalement bas, suspectez un profil de tuning, des contraintes du runtime de conteneur,
ou des événements de limite de plateforme.

Task 3: Inspect turbo/boost status

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

Ce que cela signifie : Turbo/boost est activé.

Décision : Pour des services sensibles à la latence, le turbo aide souvent (temps de service plus court).
Pour une latence déterministe, le turbo peut ajouter de la variabilité thermique ; considérez verrouiller la politique seulement après mesure.

Task 4: Verify CPU idle state availability and residency (core C-states)

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

Ce que cela signifie : Un C6 profond existe avec ~85 µs de latence de sortie (exemple). Ce n’est pas catastrophique, mais ce n’est pas gratuit.

Décision : Si vos p99 corrèlent avec des périodes d’inactivité, envisagez de limiter l’état C le plus profond seulement sur les nœuds affectés et retestez.

Task 5: Check per-state time and usage counts for idle states

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

Ce que cela signifie : CPU0 passe beaucoup de temps en C6. C’est bon pour la consommation. Cela peut être mauvais pour la latence de réveil.

Décision : Si vous observez une latence de queue, c’est votre candidat à l’enquête. Ensuite, corrélez avec les métriques applicatives et les interruptions.

Task 6: Check package C-state residency (Intel, via 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

Ce que cela signifie : Le package atteint fréquemment PC10 (sommeil profond). La puissance est basse. Excellente efficacité.
C’est aussi une cause classique de « latence de démarrage à froid » au réveil.

Décision : Si vous exécutez des charges à faible latence, envisagez de limiter les C-states du package ou d’utiliser un profil tuned faible latence sur ces nœuds.
Si vous exécutez des jobs batch, célébrez et passez à autre chose.

Task 7: Look for power limit and throttling signals (Intel RAPL / thermal)

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

Ce que cela signifie : Des fréquences boost existent, mais la puissance du package est élevée. Si les températures augmentent, vous risquez de throttler bientôt.

Décision : Si la performance est incohérente en charge, inspectez le refroidissement, les limites de puissance et le comportement du turbo soutenu avant d’accuser le noyau.

Task 8: Confirm kernel tick mode and timer behavior (idle disruption)

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

Ce que cela signifie : Le mode sans tick est activé (NO_HZ_IDLE), ce qui aide les C-states profonds. Pas complètement sans tick.

Décision : Si votre charge nécessite une latence cohérente, vous préférerez peut-être moins de transitions d’inactivité profondes (politique), pas nécessairement modifier la config du noyau.

Task 9: Identify interrupt hotspots that prevent idle or cause wake storms

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

Ce que cela signifie : Les queues NIC sont lourdes sur certains CPU. Cela peut empêcher les cœurs de s’endormir et provoquer des réveils en rafales.

Décision : Envisagez de régler l’affinité IRQ (ou le comportement de irqbalance) si vous voyez des hotspots mono-cœur ou des pics de latence alignés avec des interruptions.

Task 10: Check irqbalance status and whether it’s fighting your pinning

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)

Ce que cela signifie : irqbalance est actif. Bon réglage par défaut — sauf si vous effectuez un pinning manuel des IRQ pour la faible latence et avez oublié de le désactiver.

Décision : Si vous avez besoin d’une isolation stricte des CPU, configurez soit des CPUs bannis pour irqbalance soit désactivez-le et gérez les affinités explicitement.

Task 11: See if a tuning profile is enforcing aggressive power savings

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

Ce que cela signifie : Un profil tuned est actif, modifiant potentiellement le gouverneur CPU et d’autres réglages impactant la latence.

Décision : Pour un hôte de base de données ou un service RPC sensible à la latence, testez latency-performance (ou le profil recommandé par le fournisseur) sur un nœud canari.

Task 12: Verify current governor quickly across all 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

Ce que cela signifie : Tous les CPU sont en powersave.

Décision : Si vous poursuivez des régressions de latence, basculez un hôte unique en performance temporairement et mesurez le p99. Ne déployez pas sur toute la flotte selon des impressions.

Task 13: Temporarily change governor (and understand what you’re risking)

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

Ce que cela signifie : Vous avez demandé le gouverneur performance. Sur intel_pstate, cela change le comportement de la politique, pas une horloge fixe.

Décision : Utilisez cela comme expérience contrôlée. Si la latence s’améliore sensiblement et que le budget énergétique le permet, envisagez un profil tuned plutôt que des modifications ad hoc.

Task 14: Limit deepest C-state (surgical test, not a lifestyle)

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

Ce que cela signifie : Vous avez désactivé un état d’inactivité (ici, state3 peut être C6). Cela force un sommeil plus superficiel sur CPU0.

Décision : Si le p99 s’améliore et que la consommation augmente de façon acceptable, appliquez via une méthode persistante (args du noyau, tuned, ou unité systemd) et documentez-le.

Task 15: Check for virtualization effects: are you tuning the guest while the host decides?

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

Ce que cela signifie : Vous êtes dans une VM. Les réglages d’alimentation du guest peuvent avoir un effet limité ; la politique hôte et l’ordonnancement de l’hyperviseur pèsent davantage.

Décision : Si vous avez besoin d’un comportement faible latence, travaillez avec l’équipe plateforme : pinning CPU, gouverneur hôte et politique C-state sont les vrais leviers.

Task 16: Check CPU pressure and scheduling contention (because “idle” can be a lie)

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

Ce que cela signifie : La pression CPU est faible ; le scheduler n’est pas en difficulté. Si la latence est mauvaise, concentrez-vous sur le comportement réveil/sommeil, les interruptions, l’IO ou la contention sur les verrous.

Décision : Si some ou full est élevé, ne traquez pas d’abord les C-states — corrigez la contention, les limites CPU ou les voisins bruyants.

Feuille de diagnostic rapide

Voici l’ordre que j’utilise quand quelqu’un dit « la latence pique quand la machine est majoritairement inactive » ou « le CPU est bas mais c’est lent ».
Il est optimisé pour trouver le goulot rapidement, pas pour vous faire sentir malin.

Première étape : décidez si vous poursuivez un comportement d’alimentation CPU ou autre chose

  1. Vérifiez la pression CPU (contention du scheduler) :
    si PSI est élevé, vous n’êtes pas « inactif », vous êtes sursouscrit ou throttlé.
  2. Vérifiez la file d’exécution et le steal time (surtout en VM) :
    une faible utilisation peut coexister avec une latence élevée si vous attendez d’être ordonnancé.
  3. Vérifiez l’iowait et la latence de stockage :
    beaucoup de « CPU inactif » est en réalité « bloqué sur de l’IO ».

Deuxième étape : confirmez la politique d’alimentation active

  1. Pilote + gouverneur via cpupower frequency-info.
  2. Turbo activé ? via /sys/devices/system/cpu/cpufreq/boost.
  3. Profil tuned ou service fournisseur imposant la politique.

Troisième étape : mesurez la résidence C-state et les perturbations liées au réveil

  1. Utilisation/temps des C-states du cœur via /sys/.../cpuidle ou cpupower idle-info.
  2. C-states du package via turbostat (si disponible).
  3. Hotspots d’interruptions via /proc/interrupts et outils d’affinité IRQ.

Faites un changement à la fois, sur un nœud, avec un timer

La façon la plus rapide de perdre une semaine est d’alterner paramètres BIOS, arguments noyau et profils tuned dans la même fenêtre de maintenance.
Changez une chose, mesurez p95/p99 et puissance/thermique, puis décidez.

Trois mini-récits du monde de l’entreprise

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Une équipe a déployé une nouvelle passerelle API interne « légère ». Elle était efficace : CPU faible, courtes rafales, très axée sur les interruptions réseau.
Sur les tableaux de bord, l’utilisation CPU oscillait autour de 15–25 %. Tout le monde se félicitait de ne pas surprovisionner.
Puis le p99 a doublé pendant les heures creuses, exactement quand le trafic devenait plus calme.

La première hypothèse était classique : « moins de charge signifie plus de marge ». Mais le service était en rafales.
Pendant les périodes calmes, les CPU entraient en C-states profonds du package. Quand la rafale suivante arrivait, le traitement des requêtes payait la latence de réveil
plus la latence de montée en fréquence. Individuellement petites, collectivement moches.

La deuxième hypothèse : « On est en gouverneur performance, donc la fréquence est élevée. » Ce n’était pas le cas.
La moitié de la flotte avait un profil BIOS différent. Ces hôtes autorisaient des états package plus profonds et avaient une politique plus orientée économie d’énergie.
La flotte était hétérogène, et le load balancer mélangeait joyeusement des hôtes aux comportements de réveil différents.

La correction n’a pas été héroïque. Ils ont standardisé les profils firmware, puis testé progressivement un profil tuned faible latence uniquement sur les nœuds passerelle.
Ils ont gardé le sommeil profond activé pour les workers batch. La latence s’est stabilisée, la consommation est restée raisonnable, et l’incident s’est terminé non pas par un roman postmortem,
mais par une courte checklist ajoutée à la provision.

Mini-récit 2 : L’optimisation qui a mal tourné

Une équipe stockage (pensez : service de blocs distribué) voulait réduire la consommation. Ils ont forcé des C-states plus profonds et mis les gouverneurs en powersave sur
les nœuds de stockage. Sur le papier c’était responsable : les nœuds stockage « attendaient surtout de l’IO », et les CPU ne paraissaient pas occupés.

Ce qu’ils ont manqué, c’est la façon dont le stockage se comporte sous charges mixtes. Les chemins de complétion IO sont sensibles à la latence et pilotés par interruptions.
Le service restait calme, puis traitait soudainement une tempête de complétions, travaux de checksum et réponses réseau.
Avec des C-states profonds, la latence interruption→handler augmentait. Avec une mise à l’échelle agressive de la fréquence, les cœurs partaient lents puis montaient en cadence.

Le retour de bâton est apparu sous une forme étrange : la latence moyenne demeurait acceptable, mais la latence de queue et le jitter devenaient brutaux.
Les clients retentaient. Les retries causaient des micro-rafales. Les micro-rafales faisaient rebondir les CPU entre sommeil et réveil encore plus.
Le changement « économie d’énergie » a créé une boucle de rétroaction qui a gaspillé à la fois puissance et temps.

Ils ont annulé les changements sur les fronts de stockage mais gardé les économies d’énergie sur les nœuds de compactage en arrière-plan.
La leçon réelle fut la portée : la politique d’alimentation est spécifique à la charge. Appliquez-la par rôle, pas par cluster, et surveillez toujours le p99 et les taux de retries.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une autre entreprise gérait une flotte Kubernetes avec des générations d’instances mixtes. Leur équipe plateforme a fait quelque chose de profondément peu sexy :
ils ont maintenu une matrice de capacités matérielles et un test de provision qui enregistraient la disponibilité des C-states, le statut turbo et la résidence d’inactivité.
Chaque nouvelle mise à jour BIOS devait passer les mêmes tests avant d’être autorisée dans l’image gold.

Un trimestre, une mise à jour firmware du fournisseur a changé les limites par défaut des C-states du package.
Rien n’a explosé immédiatement. C’est le truc — ce type de modification ne casse pas toujours bruyamment. Elle modifie juste les caractéristiques de latence.

Leurs tests l’ont détecté parce que la résidence C-state du package enregistrée a changé significativement sur les nœuds inactifs.
Ils n’ont pas eu besoin d’un client pour se plaindre d’abord. Ils ont suspendu le déploiement, ajusté la politique firmware et documenté la différence.

Le résultat fut ennuyeux : aucun incident. L’équipe plateforme n’a reçu aucun éloge.
Mais les équipes applicatives n’ont jamais eu à apprendre les C-states du package à 3h du matin, et c’est la plus haute forme de succès opérationnel.

Blague n°2 : le meilleur changement de gestion d’alimentation est celui qui n’apparaît jamais dans une diapositive postmortem.

Erreurs courantes (symptômes → cause racine → correction)

1) « Le CPU est bas mais le p99 est élevé »

Symptômes : faible utilisation CPU moyenne ; gros pics de latence de queue pendant les périodes calmes ; meilleure latence sous charge soutenue.

Cause racine : C-states profonds et/ou mise à l’échelle agressive de la fréquence provoquent des pénalités de réveil et de montée en fréquence ; le trafic en rafales déclenche des transitions répétées.

Correction : mesurez la résidence C-state (cœur et package). Testez un profil faible latence en canari ou limitez les C-states les plus profonds sur les nœuds affectés.
Confirmez la cohérence des profils BIOS sur la flotte.

2) « Fréquence bloquée basse même en charge »

Symptômes : cpupower frequency-info montre une fréquence actuelle basse ; débit inférieur aux attentes ; températures CPU modérées.

Cause racine : scaling_max_freq plafonné par la politique, interactions avec les quotas CPU des conteneurs, ou contraintes de limite de puissance de la plateforme.

Correction : vérifiez scaling_max_freq et le profil tuned ; confirmez le turbo ; inspectez les limites de puissance/throttling via turbostat.
Dans les conteneurs, vérifiez les quotas CPU et les affectations cpuset.

3) « Amélioration sur un nœud mais pas sur un autre »

Symptômes : même logiciel, latence différente ; changements de tuning fonctionnent de manière incohérente selon les hôtes.

Cause racine : valeurs par défaut firmware hétérogènes, différences de microcode, ou pilotes de fréquence différents (intel_pstate vs acpi-cpufreq).

Correction : standardisez les réglages BIOS ; assurez des paramètres noyau cohérents ; inventairez la sélection de pilote et les versions microcode.

4) « Des tempêtes IRQ empêchent l’inactivité et gaspillent l’énergie »

Symptômes : le package n’atteint jamais les C-states profonds ; watts d’inactivité élevés ; certains CPU ont des comptes d’interruptions énormes.

Cause racine : déséquilibre d’affinité d’interruptions, queues NIC mal configurées, périphériques bavards, ou comportement de timer.

Correction : inspectez /proc/interrupts ; réglez l’affinité IRQ ; configurez correctement le nombre de queues ; vérifiez la configuration d’irqbalance.

5) « J’ai désactivé les C-states et maintenant le débit a chuté »

Symptômes : la consommation a augmenté ; le throttling thermique apparaît ; la performance soutenue chute après un court boost initial.

Cause racine : supprimer les économies d’inactivité augmente la température/power de base, réduisant la marge turbo et causant du throttling.

Correction : ne désactivez pas massivement les états profonds. Utilisez des politiques par rôle. Surveillez les thermiques et la puissance du package ; visez la stabilité, pas les horloges maximales.

6) « On a isolé des CPU, mais la latence jitter persiste »

Symptômes : isolation CPU configurée ; on observe toujours du jitter ; queues longues occasionnelles.

Cause racine : la gestion d’alimentation continue de faire des transitions cœur/package ; des interruptions arrivent sur des CPUs isolés ; contention entre threads SMT.

Correction : alignez l’affinité IRQ avec l’isolation ; envisagez de limiter les C-states profonds pour les cœurs isolés ; vérifiez la politique SMT pour les charges critiques en latence.

Listes de vérification / plan pas à pas

Checklist A: Standardiser une baseline d’alimentation de flotte (la partie ennuyeuse qui prévient les surprises)

  1. Inventoriez les modèles CPU, versions microcode et statut de virtualisation à travers les nœuds.
  2. Consignez le pilote de fréquence (intel_pstate/acpi-cpufreq) et les gouverneurs dans la gestion de configuration.
  3. Consignez les réglages du BIOS/UEFI (limites C-state, turbo, EPB) par génération matérielle.
  4. Définissez des politiques par rôle : criticité latence, équilibré, batch/efficacité.
  5. Appliquez des profils tuned ou équivalents via l’automatisation ; pas de configurations artisanales uniques.
  6. Échantillonnez en continu la résidence C-state du package et les watts sur des canaris inactifs pour détecter les dérives après mises à jour firmware.

Checklist B: Ajuster un nœud de service sensible à la latence (en sécurité)

  1. Base : capturez p95/p99 de latence, taux d’erreur/retry, et consommation au repos et en rafale typique.
  2. Confirmez l’absence de contention CPU : vérifiez PSI CPU et files d’attente.
  3. Mesurez la résidence C-state du package à l’idle et pendant les rafales.
  4. Changement en canari : basculez le profil tuned ou le gouverneur sur un nœud.
  5. Si toujours spiky, testez la limitation de l’état C le plus profond (temporaire) et re-mesurez.
  6. Validez thermiques et limites de puissance soutenues ; surveillez le throttling.
  7. Déployez par rôle, pas par flotte. Documentez la politique avec le « pourquoi », pas seulement le « quoi ».

Checklist C: Ajuster un nœud batch axé efficacité

  1. Confirmez que la charge vise le débit et tolère le jitter.
  2. Activez/autorisez les C-states profonds du package et des gouverneurs équilibrés.
  3. Surveillez les tempêtes d’interruptions qui gardent le package réveillé (watts gaspillés).
  4. Mesurez l’énergie par job (ou par GB traité), pas seulement le temps d’exécution.

FAQ

1) Les P-states et C-states sont-ils indépendants ?

Majoritairement, mais pas totalement. Les C-states gèrent ce qui se passe quand on est inactif ; les P-states gèrent la performance en actif.
Dans la pratique, ils interagissent via la thermique et les limites de puissance : un sommeil profond peut améliorer la marge turbo, et désactiver l’inactivité peut réduire le boost soutenu.

2) Dois-je toujours utiliser le gouverneur performance sur les serveurs ?

Non. Pour les frontends critiques en latence, cela peut aider. Pour des flottes batch, c’est souvent un gaspillage.
De plus, sur intel_pstate, performance ne signifie pas « horloge maximale fixe ». Cela signifie une politique plus agressive.
Prenez des décisions par rôle et mesurez p99 et watts.

3) Si les C-states ajoutent de la latence, pourquoi ne pas les désactiver partout ?

Parce que vous paierez en consommation, chaleur et parfois throttling — plus une marge turbo réduite.
Désactiver les C-states profonds peut être un outil ciblé pour certains rôles. Ce n’est rarement un bon défaut pour toute une flotte.

4) Pourquoi la latence s’améliore-t-elle sous charge soutenue ?

Sous charge soutenue, les cœurs restent en C0 et les fréquences se stabilisent à des niveaux supérieurs. Vous évitez les coûts de réveil et de montée en fréquence.
Les charges en rafales paient ces coûts à répétition, et la latence de queue en souffre.

5) Comment savoir si l’OS ou le matériel contrôle la fréquence ?

Commencez par cpupower frequency-info pour voir le pilote. Sur les Intel modernes, intel_pstate en mode actif signifie que le matériel joue un grand rôle.
Regardez aussi si la fréquence courante est « asserted by call to hardware » dans la sortie.

6) La virtualisation change-t-elle l’histoire ?

Oui. L’état d’inactivité d’un invité est médié par l’hyperviseur. La fréquence et le sommeil package profond sont typiquement contrôlés par l’hôte.
Si vous réglez à l’intérieur d’une VM et ne voyez pas d’effet, ce n’est pas parce que vous êtes malchanceux ; c’est parce que vous ne manipulez pas les bons leviers.

7) Quelle est la différence opérationnelle entre C-states du cœur et du package ?

Les C-states du cœur affectent la profondeur de sommeil d’un seul cœur et la latence de réveil. Les états package affectent les composants au niveau du socket et peuvent économiser beaucoup plus d’énergie.
Les états package peuvent aussi entraîner des pénalités plus visibles sur la « première requête après l’inactivité », selon la plateforme.

8) L’ajustement des interruptions peut-il corriger la latence liée aux C-states ?

Parfois. Si des interruptions réveillent constamment des cœurs inactifs, vous verrez du gaspillage d’énergie et du jitter.
Si les interruptions sont concentrées sur quelques CPU, ces CPU peuvent ne jamais dormir tandis que d’autres plongent profondément, créant un comportement de réponse inégal.
Équilibrer ou épingler correctement les interruptions peut stabiliser la latence.

9) Comment choisir entre modes « faible latence » et « économe en énergie » ?

Utilisez le SLO de la charge et le modèle de coût. Si vous avez des cibles p99 strictes et du trafic en rafales, penchez vers faible latence sur ces nœuds.
Si vous avez des jobs batch ou des files élastiques, privilégiez l’efficacité. Évitez de mélanger des politiques dans le même pool derrière un load balancer.

10) Quelle est la première expérience sûre si je suspecte les C-states ?

Faites un canari sur un seul nœud : capturez la baseline, puis passez à un profil tuned faible latence ou limitez temporairement l’état d’inactivité le plus profond.
Si le p99 s’améliore sans déclencher de throttling ni d’augmentation inacceptable de la consommation, vous avez prouvé la causalité.

Conclusion : étapes pratiques suivantes

« Inactif » n’est pas un état neutre. C’est une décision active prise par des couches de silicium, firmware et code noyau — chacune tentant d’économiser de l’énergie,
et occasionnellement vous volant votre budget de latence au passage.

Étapes suivantes qui tiennent réellement en production :

  1. Mesurez avant d’ajuster : collectez pilote/gouverneur, résidence C-state et p95/p99 sur un nœud canari.
  2. Standardisez la politique firmware : des valeurs BIOS incohérentes tuent silencieusement une flotte.
  3. Séparez par rôle : nœuds faible-latence et nœuds efficacité ne doivent pas partager la même politique d’alimentation.
  4. Rendez les changements réversibles : bascules via profils tuned ou gestion de configuration, pas des SSH artisanaux.
  5. Surveillez la latence de queue et les retries : les moyennes vous mentiront avec un sérieux aplomb.
← Précédent
Cache CPU (L1/L2/L3) en clair : pourquoi la mémoire gagne
Suivant →
NTP entre bureaux : la petite chose qui casse AD, VPN et les certificats

Laisser un commentaire