Big.LITTLE débarque sur x86 : comment les idées d’ARM sont passées aux PC

Cet article vous a aidé ?

Vous achetez un PC « plus rapide ». Votre compilation met plus de temps, votre jeu saccade, ou votre budget de latence ressemble soudain à de la fiction.
Les graphiques indiquent que le CPU est « seulement à 40 % », mais le service fond quand même. Bienvenue dans le x86 hybride : tous les cœurs ne se valent pas,
et votre ordonnanceur fait maintenant partie de votre contrat de performance.

La philosophie Big.LITTLE d’ARM — mélanger des cœurs rapides et des cœurs efficaces — a quitté les téléphones pour atterrir dans les portables, les
bureaux et de plus en plus dans des stations de travail. La bonne nouvelle : meilleur rendement perf/watt et plus de débit sous contraintes de puissance.
La mauvaise nouvelle : si vous supposez qu’« un cœur est un cœur », vous livrerez des surprises.

Ce qui a réellement changé quand le x86 est devenu hybride

La planification de capacité classique x86 supposait un multiprocesseur symétrique : les cœurs différaient surtout par la fréquence à un instant donné,
pas par la microarchitecture. Si vous aviez 16 cœurs, vous planifiiez comme si vous aviez 16 moteurs à peu près comparables. Les architectures hybrides brisent délibérément cette hypothèse.

Sur le x86 hybride moderne (le plus visible étant Alder Lake et ses successeurs d’Intel), vous obtenez :

  • P-cores (cœurs de performance) : cœurs out-of-order larges, meilleure performance mono‑thread, souvent avec SMT/Hyper-Threading.
  • E-cores (cœurs d’efficacité) : cœurs plus petits, meilleur débit par watt, typiquement sans SMT, souvent regroupés en grappes.

Ce mélange est une stratégie de gestion d’énergie déguisée en CPU. Sous des limites de puissance strictes, les E-cores peuvent prendre en charge le travail d’arrière-plan à moindre coût
pendant que les P-cores sprinters. Sous un fort débit, les E-cores ajoutent des « voies » supplémentaires, mais pas de la même largeur.
Si vous les traitez comme identiques, vous placerez de travers des threads critiques en latence et ensuite vous accuserez « l’overhead Linux » comme en 2007.

L’OS doit répondre à une nouvelle question : où ce thread doit-il s’exécuter compte tenu de son comportement et des capacités du cœur ?
C’est de l’ordonnancement plus des indices plus de la télémétrie. C’est aussi un combat de politiques : maximise-t-on le débit, minimise-t-on la latence de queue,
réduit-on la consommation, ou garde-t-on l’interface réactive ? La réponse change selon la charge de travail, et elle change au cours de la journée.

Un CPU hybride ressemble à un datacenter avec deux types d’instances : certaines sont rapides et chères, d’autres plus lentes mais abondantes.
Si votre autoscaler ne comprend pas cela, félicitations — vous avez inventé une nouvelle sorte de « voisin bruyant CPU ».

Une vérité sèche : l’observabilité compte plus aujourd’hui. Quand vous voyez « CPU 40 % », vous devez demander quel CPU, à quelle fréquence,
avec quel taux de migration, sous quelles limites de puissance.

Contexte historique : la version courte et concrète

L’hybride n’est pas apparu de nulle part. C’est une chaîne de contraintes de puissance, de leçons mobiles et de compromis de bureau.
Voici des faits concrets à retenir car ils expliquent le comportement d’aujourd’hui.

  1. 2011–2013 : ARM a popularisé Big.LITTLE comme moyen d’équilibrer performance et autonomie, utilisant initialement des grappes « big » et « little ».
  2. 2015–2017 : Les ordonnanceurs ont mûri du « basculement de grappes » vers un placement de tâches plus fin ; le mobile a fait de cela un problème OS de première importance.
  3. Intel a déjà tenté l’hétérogénéité : des exemples incluent la réflexion Atom + Core, et plus tard « Lakefield » (une puce x86 hybride) comme précurseur.
  4. Alder Lake (12e gen Core) : a rendu l’hybride grand public sur desktops/portables, forçant Windows et Linux à s’adapter à l’échelle grand public.
  5. Intel Thread Director : télémétrie matérielle qui conseille l’ordonnanceur OS sur le comportement d’un thread (compute-heavy, lié à la mémoire, etc.).
  6. Windows 11 : lancé avec des améliorations explicites de l’ordonnancement hybride ; Windows 10 se comportait souvent « correctement » jusqu’à ce que ce ne soit plus le cas.
  7. Héritage Linux EAS : Energy Aware Scheduling a grandi sur ARM ; cette expérience a alimenté la capacité de Linux à raisonner sur les compromis énergie/performance.
  8. Les limites de puissance sont devenues centrales : PL1/PL2 (et les politiques firmware des vendeurs) peuvent dominer la performance réelle plus que les fréquences turbo annoncées.
  9. L’asymétrie SMT compte : les P-cores peuvent présenter deux CPUs logiques ; les E-cores généralement non — donc le « nombre de vCPU » peut vous tromper.

Réalité de l’ordonnancement : P-cores, E-cores et le marché avec l’OS

L’hybride signifie que l’ordonnanceur fait désormais partie de votre architecture

Sur des CPU symétriques, le travail de l’ordonnanceur consiste principalement en équité, répartition de charge et localité du cache. Sur hybride, c’est aussi classification et
placement. C’est plus difficile parce que le « bon » cœur dépend de ce que le thread fait à cet instant.

Si vous êtes SRE, vous devriez penser à Thread Director (ou tout mécanisme similaire) comme à un « profilage runtime pour l’ordonnancement ».
Ça aide. Ce n’est pas magique. Cela crée aussi une dépendance : le meilleur placement requiert souvent un support OS, microcode et firmware
qui se comportent comme une unité.

Ce que l’OS essaie d’optimiser

  • Réactivité : garder les threads interactifs sur les P-cores, éviter les chutes de fréquence qui causent du lag UI.
  • Débit : répartir le travail d’arrière-plan ou parallèle sur les E-cores, préserver les P-cores pour les heavy hitters.
  • Énergie : exécuter le travail « bon marché » sur les E-cores à tension/fréquence réduite, maintenir la puissance du package dans les limites.
  • Thermique : éviter le turbo soutenu sur les P-cores si cela déclenche du throttling qui nuit à tout par la suite.
  • Localité du cache : les migrations ne sont pas gratuites ; l’hybride augmente la tentation de migrer, ce qui peut se retourner contre vous.

Ce qui peut mal tourner : trois vérités fondamentales

Premièrement, une charge peut être « compute-heavy » mais sensible à la latence. Si l’OS la déplace « utilement » vers des E-cores parce qu’elle ressemble à un travail d’arrière-plan,
votre p99 explose.

Deuxièmement, la puissance est partagée au niveau du package. Si les E-cores se réveillent et consomment de la puissance, les P-cores peuvent perdre de la marge turbo.
Vous pouvez ajouter du débit et réduire la performance mono‑thread en même temps. Ça semble illégal, mais c’est la physique.

Troisièmement, la topologie est embrouillée. Les E-cores peuvent être regroupés ; les P-cores ont des frères SMT ; certains cœurs partagent L2/L3 de façons différentes.
Le « pinning » n’est plus une simple histoire « core 0–N » à moins d’inspecter votre cartographie réelle.

Paraphrase d’une idée de Werner Vogels : Tout échoue, tout le temps ; construisez des systèmes qui l’acceptent et continuent d’opérer.
L’ordonnancement hybride est une petite version de cela. Supposez que les mauvais placements arrivent et instrumentez-les.

Petite blague #1 : Les CPU hybrides sont les premiers silicons qui peuvent lancer votre compilation en « mode éco » sans demander — parce que l’ordonnanceur se sent zen aujourd’hui.

Où ça casse en production : modes de défaillance reconnaissables

1) Pics de latence de queue avec un CPU moyen « normal »

Le graphique classique : le CPU moyen va bien, la charge moyenne va bien, mais le p99 s’effondre. Sur hybride, cela peut arriver quand les threads les plus chauds
atterrissent sur des E-cores ou rebondissent entre types de cœurs. La moyenne reste polie ; la queue brûle votre SLO.

Cherchez des augmentations de context switches, des migrations et des oscillations de fréquence. Vérifiez aussi les limites de puissance : le throttling du package peut créer
des ralentissements périodiques qui corrèlent avec la température ou la charge soutenue.

2) Les benchmarks mentent parce que l’OS et la politique d’alimentation font partie du benchmark

Si vous lancez un benchmark une fois et déclarez victoire, vous mesurez la chance. L’hybride ajoute de la variabilité : des démons d’arrière-plan peuvent voler des P-cores ;
le governor peut plafonner les fréquences ; le firmware peut appliquer des limites silencieuses.

3) Surprises en virtualisation : les vCPU ne sont pas égaux

Une VM épinglée à « 8 vCPUs » peut en réalité être épinglée à « 8 E-cores en termes de performance », tandis qu’une autre VM obtient des P-cores.
Sans pinning explicite et conscience NUMA/topologie, vous pouvez créer des classes de performance par accident.

4) Charges de stockage et réseau qui deviennent bizarres

Les stacks de stockage ont des threads sensibles à la latence (gestion des interruptions, complétion IO, journaling). Mettez-les sur des E-cores sous charge
et vous obtiendrez du jitter. Pendant ce temps, les threads de débit peuvent occuper les E-cores et paraître « efficaces », jusqu’à ce que le chemin de complétion IO
devienne le goulot.

5) Thrash lié aux limites de puissance

Les rafales PL2 sont agréables pour les tâches courtes. Sous charge soutenue, le firmware vous ramène à PL1, parfois agressivement.
Si votre charge alterne entre phases rafales et soutenues (compilations, compactages, ETL), vous pouvez voir une performance dépendante de la phase qui ressemble à une régression,
mais c’est la politique de puissance.

Tâches pratiques : commandes, sorties et décisions (12+)

Voici les vérifications que j’exécute réellement quand quelqu’un dit « cette machine hybride est plus lente que l’ancienne. »
Chaque tâche inclut : la commande, ce que la sortie signifie, et la décision que vous prenez.
Les commandes supposent Linux ; quand Windows est pertinent, je le souligne.

Task 1: Confirm you’re on a hybrid CPU and see topology

cr0x@server:~$ lscpu
Architecture:                         x86_64
CPU(s):                               24
Thread(s) per core:                   2
Core(s) per socket:                   16
Socket(s):                            1
Model name:                           12th Gen Intel(R) Core(TM) i7-12700K
Flags:                                ... hwp ...

Ce que cela signifie : « CPU(s): 24 » avec « Core(s) per socket: 16 » et SMT=2 indique un mélange (8 P-cores avec SMT = 16 threads, plus 4 E-cores = 4 threads → 20 ; ajustez selon le modèle).
Sur certains modèles vous verrez des totaux qui n’ont de sens qu’avec un hybride.

Décision : Si les comptes ne se réconcilient pas proprement, traitez le système comme hétérogène et cessez d’utiliser « CPU% » comme un scalaire unique dans les discussions.

Task 2: Identify which logical CPUs are P-core vs E-core

cr0x@server:~$ lscpu -e=CPU,CORE,SOCKET,NODE,ONLINE,MAXMHZ,MINMHZ
CPU CORE SOCKET NODE ONLINE MAXMHZ MINMHZ
0   0    0      0    yes    4900.0 800.0
1   0    0      0    yes    4900.0 800.0
...
16  12   0      0    yes    3600.0 800.0
17  13   0      0    yes    3600.0 800.0

Ce que cela signifie : Si certains CPUs ont un MAXMHZ plus bas, ce sont souvent des E-cores (pas infaillible, mais indice fort).
Les CPUs logiques appariés (même CORE) suggèrent du SMT sur les P-cores.

Décision : Créez une liste « P set » et « E set » pour le pinning et les benchmarks. Ne devinez pas.

Task 3: Check kernel view of core types (if available)

cr0x@server:~$ grep . /sys/devices/system/cpu/cpu*/topology/core_type 2>/dev/null | head
/sys/devices/system/cpu/cpu0/topology/core_type:1
/sys/devices/system/cpu/cpu8/topology/core_type:0

Ce que cela signifie : Certains kernels exposent core_type (les valeurs varient selon la plateforme). La présence indique que le kernel est conscient de l’hybride.

Décision : Si cela n’existe pas, soyez plus conservateur : basez-vous sur la caractérisation des performances et le pinning plutôt que de supposer que l’ordonnanceur fait toujours le bon choix.

Task 4: See current frequency behavior per CPU

cr0x@server:~$ sudo turbostat --quiet --show CPU,Core,Avg_MHz,Bzy_MHz,Busy%,PkgWatt --interval 1 --num_iterations 3
CPU Core  Avg_MHz Bzy_MHz Busy% PkgWatt
-   -     820     3100    12.3  18.4
-   -     790     2800    11.8  18.1
-   -     910     3400    14.6  21.2

Ce que cela signifie : Avg_MHz montre la fréquence effective incluant l’idle ; Bzy_MHz montre la fréquence en charge. Si le Bzy_MHz est bas sous charge, vous pouvez être limité par la puissance ou épinglé sur des E-cores.

Décision : Si le Bzy_MHz s’effondre quand les E-cores se réveillent, vous voyez une contention de puissance du package. Envisagez d’isoler les P-cores pour le travail à latence ou d’ajuster les limites de puissance/le governor.

Task 5: Check CPU governor and driver (policy matters)

cr0x@server:~$ cpupower frequency-info
analyzing CPU 0:
  driver: intel_pstate
  CPUs which run at the same hardware frequency: 0 1 2 3 4 5 6 7
  available cpufreq governors: performance powersave
  current policy: frequency should be within 800 MHz and 4900 MHz.
                  The governor "powersave" may decide which speed to use

Ce que cela signifie : intel_pstate avec powersave est courant et pas intrinsèquement mauvais. Mais la politique interagit avec l’ordonnancement hybride et les caps de puissance.

Décision : Pour des serveurs sensibles à la latence, testez performance ou ajustez la fréquence min ; pour les portables, gardez powersave mais validez la latence de queue sous charge réaliste.

Task 6: Spot throttling (thermal or power) in kernel logs

cr0x@server:~$ sudo dmesg -T | egrep -i 'throttl|thermal|powercap|pstate' | tail -n 8
[Mon Jan 10 10:21:33 2026] intel_pstate: Turbo disabled by BIOS or power limits
[Mon Jan 10 10:21:37 2026] thermal thermal_zone0: throttling, current temp: 96 C

Ce que cela signifie : Vous ne faites pas benchmarker l’architecture CPU ; vous benchmarkez le refroidissement et la politique firmware.

Décision : Améliorez le refroidissement, ajustez PL1/PL2, ou cessez d’attendre un turbo soutenu. Si c’est un serveur, traitez cela comme un incident de configuration hardware/firmware.

Task 7: Check powercap constraints (RAPL)

cr0x@server:~$ sudo powercap-info -p intel-rapl
Zone: intel-rapl:0 (package-0)
  enabled: 1
  power limit 0: 125.00 W (enabled)
  power limit 1: 190.00 W (enabled)

Ce que cela signifie : Ces limites peuvent dominer si les P-cores atteignent le boost attendu sous une charge mixte incluant des E-cores.

Décision : Si vous exécutez des services sensibles à la latence, envisagez de réduire la charge d’arrière-plan ou de réserver de la marge plutôt que d’augmenter les limites de puissance et espérer que les ventilateurs gagnent.

Task 8: Observe migrations and context switches (scheduler thrash)

cr0x@server:~$ pidstat -w -p 1234 1 3
Linux 6.6.0 (server)  01/10/2026  _x86_64_  (24 CPU)

11:02:01 PM   UID       PID   cswch/s nvcswch/s  Command
11:02:02 PM  1000      1234   1200.00    540.00  myservice
11:02:03 PM  1000      1234   1188.00    601.00  myservice

Ce que cela signifie : Des context switches volontaires/involontaires élevés peuvent indiquer contention de locks, attentes IO, ou préemption/migrations fréquentes.
Sur systèmes hybrides, cela peut aussi être signe que des threads sont renvoyés pour « équilibrer » la charge.

Décision : Si les taux de cswitch sont élevés pendant les pics de latence, inspectez l’affinité CPU, les cgroups cpusets, et les réglages d’ordonnancement ; n’ajoutez pas juste des cœurs.

Task 9: Confirm where a process is actually running

cr0x@server:~$ ps -o pid,psr,comm -p 1234
  PID PSR COMMAND
 1234  17  myservice

Ce que cela signifie : PSR est le dernier CPU sur lequel le process a tourné. Si vous mappez 17 à votre ensemble E-core, c’est votre preuve fumante.

Décision : Pour les processus critiques en latence, épinglez-les aux P-cores (prudemment) ou utilisez des cpusets pour que l’ordonnanceur puisse encore équilibrer à l’intérieur des « bons » cœurs.

Task 10: Pin a workload for controlled tests (taskset)

cr0x@server:~$ taskset -cp 0-7 1234
pid 1234's current affinity list: 0-23
pid 1234's new affinity list: 0-7

Ce que cela signifie : Vous avez restreint le processus aux CPUs 0–7. Si ce sont des P-cores (vérifiez !), vous l’avez protégé du placement sur E-cores.

Décision : Si la latence de queue s’améliore immédiatement, vous avez un problème d’ordonnancement/placement, pas un problème « l’application est devenue lente ».

Task 11: Use cgroups cpuset for policy instead of one-off pinning

cr0x@server:~$ sudo mkdir -p /sys/fs/cgroup/cpuset/latency
cr0x@server:~$ echo 0-7 | sudo tee /sys/fs/cgroup/cpuset/latency/cpuset.cpus
0-7
cr0x@server:~$ echo 0 | sudo tee /sys/fs/cgroup/cpuset/latency/cpuset.mems
0
cr0x@server:~$ echo 1234 | sudo tee /sys/fs/cgroup/cpuset/latency/cgroup.procs
1234

Ce que cela signifie : Vous avez créé un cgroup cpuset et déplacé le process dedans. C’est moins fragile que taskset par processus dans l’automatisation.

Décision : Standardisez : exécutez les tiers latence sur des cpusets P-core ; exécutez les tâches batch sur des cpusets E-core. Puis validez que la contention de puissance ne compromet pas vos gains.

Task 12: Check IRQ placement (storage/network latency’s quiet killer)

cr0x@server:~$ cat /proc/interrupts | head -n 6
           CPU0       CPU1       CPU2       CPU3       CPU4       CPU5
  16:     10234          0          0          0          0          0   IO-APIC   16-fasteoi   i8042
  33:    882301     120333     110221      99881      93211      88110   PCI-MSI 524288-edge      nvme0q0

Ce que cela signifie : Si les interruptions des périphériques clés sont traitées majoritairement sur des E-cores (ou un CPU surchargé), la latence de complétion IO peut jitter.

Décision : Envisagez d’épingler les IRQ critiques sur les P-cores (ou un ensemble dédié) pour des chemins stockage/réseau à faible latence — surtout sur des systèmes avec un fort PPS ou un fort IOPS.

Task 13: Confirm per-core utilization and steal time (virtualization)

cr0x@server:~$ mpstat -P ALL 1 1 | egrep 'Average|all| 0 | 8 | 16 '
Average:     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %idle
Average:     all   35.12    0.00    9.44    0.80    0.00    0.70    3.10  50.84
Average:       0   62.00    0.00   12.00    0.00    0.00    0.00    0.00  26.00
Average:       8   18.00    0.00    5.00    0.00    0.00    0.00    7.00  70.00
Average:      16   10.00    0.00    2.00    0.00    0.00    0.00    0.00  88.00

Ce que cela signifie : Certains CPUs sont beaucoup plus occupés ; %steal indique que l’hyperviseur prend du temps. L’hybride aggrave cela quand les vCPUs mappent mal aux types de cœurs.

Décision : Si le steal est élevé ou si les CPUs occupés correspondent aux E-cores, revoyez le pinning des VM et les ensembles CPU de l’hôte. Ne « corrigez » pas d’abord à l’intérieur du guest.

Task 14: Profile hotspots quickly (perf top)

cr0x@server:~$ sudo perf top -p 1234
Samples: 14K of event 'cycles', 4000 Hz, Event count (approx.): 2987654321
  22.11%  myservice  libc.so.6          [.] memcpy_avx_unaligned_erms
  11.03%  myservice  myservice          [.] parse_request
   6.40%  kernel     [kernel]           [.] finish_task_switch

Ce que cela signifie : Si finish_task_switch apparaît fortement, le coût d’ordonnancement/migrations peut faire partie du problème. Si ce sont des hotspots applicatifs purs, le placement hybride peut être secondaire.

Décision : Symboles kernel d’ordonnancement élevés + pics de latence → inspectez l’affinité/cgroups et les taux de migration. Principalement des symboles applicatifs → optimisez le code ou réduisez la contention en premier.

Petite blague #2 : Rien n’enseigne l’humilité comme une machine « 24 cœurs » dont la moitié des cœurs sont vraiment une suggestion.

Cahier de diagnostic rapide

L’objectif est de trouver le goulot en minutes, pas en heures, et d’éviter le piège du « benchmark de mes sensations ».
Voici l’ordre qui donne généralement le signal le plus vite sur le x86 hybride.

Première étape : confirmez qu’il s’agit d’un problème de placement, pas d’un problème de capacité pur

  • Vérifiez la latence de queue vs CPU moyen : si le p99 est mauvais alors que le CPU moyen est modéré, suspectez le placement ou le throttling.
  • Vérifiez l’occupation et la fréquence par CPU : utilisez mpstat + turbostat. Cherchez des CPUs bloqués pendant que d’autres sont inactifs, et un Bzy_MHz bas.
  • Vérifiez migrations/context switches : pidstat -w, perf top pour finish_task_switch.

Deuxième étape : éliminez les caps power/thermiques (le limiteur silencieux)

  • dmesg pour throttling : logs thermal/powercap.
  • Limites RAPL : voyez si les limites du package sont basses pour la classe de workload.
  • Réalité du refroidissement : si c’est une tour avec un ventirad bas de gamme, vous n’exécutez pas « un CPU », vous exécutez « un radiateur d’appoint avec des opinions ».

Troisième étape : isolez par politique — P-cores pour la latence, E-cores pour le batch

  • Épinglez une réplique : déplacez une instance dans un cpuset P-core et comparez le p99.
  • Déplacez les jobs d’arrière-plan : épinglez compactages, sauvegardes, indexation, builds CI sur les E-cores.
  • Validez les services système : assurez-vous que les IRQs et ksoftirqd ne sont pas coincés sur votre grappe E-core.

Quatrième étape : si c’est encore mauvais, traitez comme un incident classique de performance

  • Contention de locks, comportement de l’allocateur, attentes IO, churn du cache page, pauses GC.
  • L’hybride peut amplifier ces problèmes, mais il les invente rarement de toutes pièces.

Erreurs courantes : symptôme → cause racine → correctif

1) Symptom: p99 latency doubled after “CPU upgrade,” but averages look fine

Cause racine : les threads sensibles à la latence sont ordonnancés sur des E-cores ou migrent entre types de cœurs ; ou les P-cores perdent leur turbo à cause de la contention de puissance du package.

Correctif : créez des cpusets P-core pour le niveau latence ; déplacez le batch/arrière-plan sur les E-cores ; vérifiez avec ps -o psr et turbostat.

2) Symptom: build/test pipeline slower on a machine with more “threads”

Cause racine : les threads SMT sur P-cores gonflent le nombre de CPUs logiques ; le parallélisme réglé sur les CPUs logiques surcharge des ressources partagées ; les E-cores n’ont pas le même IPC que les P-cores.

Correctif : limitez les jobs parallèles aux P-cores physiques pour les étapes sensibles ; exécutez les étapes embarrassingly parallel sur les E-cores ; ajustez make -j ou la concurrence CI.

3) Symptom: sporadic stutter under mixed load; disappears when background jobs are stopped

Cause racine : la charge d’arrière-plan sur les E-cores consomme de la puissance du package et déclenche des baisses de fréquence ou du throttling qui affectent les P-cores.

Correctif : planifiez le batch en heures creuses ; limitez CPU du batch avec des cgroups ; maintenez une marge thermique ; évitez de courir après PL2 en permanence.

4) Symptom: VM A consistently slower than VM B on identical configs

Cause racine : le host a épinglé différemment les vCPUs (trop d’E-cores vs P-cores), ou l’ordonnanceur de l’hôte a regroupé une VM sur des E-cores.

Correctif : épinglez les vCPUs des VM sur des classes de cœurs cohérentes ; documentez la politique ; validez avec mpstat et la topologie au niveau hôte.

5) Symptom: NVMe latency jitter after enabling “all cores” and max throughput mode

Cause racine : IRQs/softirqs atterrissent sur des E-cores ou sur des CPUs surchargés ; les threads de complétion IO sont affamés.

Correctif : rééquilibrez l’affinité des IRQs ; réservez quelques P-cores pour l’IO et le réseau ; confirmez la distribution des interruptions dans /proc/interrupts.

6) Symptom: performance regressions differ between Windows 10 and Windows 11

Cause racine : différents supports d’ordonnancement hybride ; Thread Director utilisé différemment ; plans d’alimentation divergents.

Correctif : standardisez les versions OS pour les flottes sensibles à la performance ; alignez les plans d’alimentation ; validez avec des tests de pinning répétables.

7) Symptom: “CPU utilization is low” but run queue is high

Cause racine : threads exécutable(s) attendent les P-cores pendant que des E-cores restent inactifs (ou vice-versa) à cause de contraintes cpuset ou décisions d’ordonnancement ; possible cap de fréquence.

Correctif : inspectez les cpusets et affinités ; testez un ensemble P-core élargi ; vérifiez le governor et les caps de puissance ; évitez l’isolation accidentelle qui laisse de la capacité inutilisée.

Trois mini-récits d’entreprise de l’ère hybride

Mini-story 1: The incident caused by a wrong assumption

Une équipe a déplacé une couche API sensible à la latence depuis des serveurs plus anciens et symétriques vers de nouvelles machines de type poste de travail développeur qui étaient « disponibles tout de suite ».
La fiche technique semblait excellente : plus de cœurs, fréquences boost plus élevées, moderne en tout. La migration a été traitée comme un redimensionnement de routine.

Le premier symptôme n’était pas un plantage. C’était le pire type d’échec : une lente saignée. Le p95 a augmenté progressivement, puis le p99 a déclenché des alertes aux heures de pointe.
Le CPU moyen tournait autour de 50 %. La charge moyenne était sans histoire. L’astreinte a effectué le rituel habituel : scale out, restart, accuser le dernier déploiement.
Rien n’a fait bouger durablement l’aiguille.

La mauvaise hypothèse était ancrée dans leur modèle mental : « 16 cœurs, c’est 16 cœurs ». Le runtime avait un thread pool dimensionné sur les CPUs logiques.
Sous charge rafale, une partie des threads de requête atterrissait sur des E-cores pendant que le GC et quelques maintenances d’arrière-plan se réveillaient. Le package a atteint une limite de puissance,
les P-cores ont perdu leur marge turbo, et l’ordonnanceur a commencé à migrer comme s’il résolvait un sudoku en temps réel.

Le correctif fut ennuyeux mais décisif. Ils ont construit une politique cpuset : le traitement des requêtes et les boucles d’événements restaient sur les P-cores ; les tâches d’arrière-plan étaient épinglées sur les E-cores.
Ils ont aussi réduit la taille du thread pool pour qu’elle se rapproche de la « capacité P-core » au lieu du « nombre de CPUs logiques ». La latence de queue est revenue à la normale sans ajouter de machines.

L’action de postmortem qui a compté : mettre à jour la doc de capacity planning pour traiter l’hybride comme du calcul hétérogène. Plus de dimensionnement « uniquement par nombre de cœurs ».
Ce n’est pas un changement philosophique ; c’est éviter la fatigue des astreintes.

Mini-story 2: The optimization that backfired

Une autre organisation faisait tourner une pipeline d’ingestion à haut débit. Elle était majoritairement CPU-bound pour le parsing avec des rafales IO occasionnelles.
Ils ont remarqué que les E-cores étaient sous-utilisés et ont décidé de « débloquer des performances gratuites » en augmentant la concurrence des workers jusqu’à saturer tous les CPUs logiques.
Le benchmark a montré un joli gain de débit le premier jour. Champagne.

Puis la production est arrivée. La pipeline d’ingestion vivait à côté d’un service de requêtes orienté utilisateur sur la même classe d’hôte.
Sous trafic réel, l’ingestion a monté en charge, les E-cores se sont occupés, la puissance du package a augmenté, et les P-cores du service de requêtes ont perdu leur boost.
La latence des requêtes est devenue saccadée. Pas systématiquement mauvaise — juste assez pour éroder la confiance et déclencher des retries. Les retries ont augmenté la charge. La boucle classique,
maintenant alimentée par l’hétérogénéité du silicium.

L’équipe a d’abord cherché des « problèmes réseau » parce que les pics corrélaient avec les montées de débit. Ils ont ajusté les buffers TCP, les files NIC,
ils ont tout retouché sauf la contrainte partagée réelle : la puissance du package et le placement d’ordonnancement.

Le correctif final a été de réduire la concurrence d’ingestion et de la confiner explicitement aux E-cores avec une quota CPU, laissant de la marge de puissance pour les P-cores.
Le débit a légèrement chuté par rapport au benchmark labo, mais la performance visible par l’utilisateur s’est améliorée. En production, la stabilité est une fonctionnalité,
pas un bonus.

La leçon était désagréable mais utile : « utiliser tous les cœurs » n’est pas une optimisation universelle sur les CPUs hybrides. Parfois, le système le plus rapide est celui qui
laisse de la capacité de côté pour éviter de déclencher la mauvaise limite.

Mini-story 3: The boring but correct practice that saved the day

Une équipe plateforme avait une règle qui agaçait les développeurs : chaque nouvelle classe de hardware devait passer une petite « suite d’acceptation fiabilité ».
Pas un zoo massif de benchmarks — juste un ensemble répétable : fréquence CPU sous charge soutenue, latence queue sous charge mixte, détection de throttling,
contrôles de distribution d’IRQ, et validation du pinning.

Quand des machines x86 hybrides sont arrivées, la suite a immédiatement révélé deux problèmes. Premièrement, les réglages firmware par défaut imposaient des limites de puissance conservatrices,
causant une performance soutenue bien en dessous des attentes. Deuxièmement, leur image de base avait un scanner de sécurité d’arrière-plan planifié en heures ouvrées,
qui consommant volontiers des E-cores — réduisant le boost des P-cores aux heures de pointe.

Parce que cela a été trouvé avant la production, les corrections ont été banales : ajuster la politique firmware pour correspondre à la classe de workload, replanifier le scanner d’arrière-plan,
et fournir un template de service basé sur cpuset pour les tiers latence. Pas d’héroïsme, pas de salle de crise, pas de « pourquoi le tableau de bord du PDG est lent ».

Cette suite n’a rendu personne célèbre. Elle a empêché un déploiement chaotique et a évité à l’organisation d’apprendre l’ordonnancement hybride à la dure.
En opérations, l’ennuyeux est un compliment.

Checklists / plan pas à pas

Étape par étape : introduire le x86 hybride dans une flotte sans drame

  1. Inventoriez la topologie : enregistrez la cartographie P/E core, la présence SMT, et les fréquences max par classe de cœur.
  2. Standardisez le firmware : alignez les limites de puissance et la politique thermique par classe de workload (latence vs débit).
  3. Choisissez une stratégie OS : ne mélangez pas « quel kernel était sur l’image » entre nœuds hybrides ; la maturité de l’ordonnanceur compte.
  4. Définissez des tiers : décidez quels services sont critiques en latence vs batch/débit. Notez-le.
  5. Implémentez des cpusets : cpuset P-core pour le tier latence ; cpuset E-core pour le batch ; laissez un petit ensemble partagé pour l’OS/housekeeping si nécessaire.
  6. Hygiène des IRQ : assurez-vous que les IRQs stockage/réseau atterrissent sur des cœurs qui ne seront pas affamés ; vérifiez la distribution dans /proc/interrupts.
  7. Baserlinez avec charge mixte : lancez le tier latence pendant que le tier batch est actif ; les échecs hybrides apparaissent souvent sous contention.
  8. Observez fréquence et throttling : capturez turbostat sous charge soutenue ; grep les logs pour thermal/powercap events.
  9. Définissez des garde-fous : limitez le CPU du batch avec des quotas ; évitez les defaults « utiliser tous les CPUs » dans la CI et les jobs d’arrière-plan.
  10. Déployez des canaris : comparez p50/p95/p99 et taux d’erreur entre nœuds symétriques et hybrides sous trafic réel.
  11. Documentez la politique : quels CPUs sont la « voie rapide », ce qui est épinglé, et qui possède le droit de le modifier.
  12. Retestez après mises à jour : microcode, kernel, et mises à jour OS peuvent changer le comportement d’ordonnancement. Traitez-les comme des changements pertinents pour la performance.

Checklist : quand quelqu’un dit « l’hybride est plus lent »

  • Savons-nous quels CPUs sont P vs E sur cet hôte ?
  • Les threads critiques en latence tournent-ils sur des E-cores ?
  • Subissons-nous du throttling power/thermique ?
  • La concurrence a-t-elle augmenté parce que « plus de threads » sont apparus ?
  • Les IRQs atterrissent-elles sur les mauvais cœurs ?
  • La version OS ou le plan d’alimentation ont-ils changé ?
  • L’épinglage d’une instance sur des P-cores peut-il reproduire/améliorer le problème ?

FAQ

1) Is Big.LITTLE on x86 the same as ARM Big.LITTLE?

Conceptuellement similaire (cœurs hétérogènes pour le perf-per-watt), mécaniquement différent. L’écosystème ARM a mûri plus tôt avec l’hétérogénéité,
et le support d’ordonnancement a été façonné par les contraintes mobiles. Sur x86, le principe est le même, mais la topologie, le firmware et les attentes héritées diffèrent.

2) Why does average CPU look fine while latency is bad?

Parce que la moyenne masque le placement. Quelques threads chauds sur des E-cores peuvent dominer le p99 même si beaucoup d’autres cœurs sont inactifs.
De plus, les limites de puissance peuvent réduire la fréquence des P-cores sans pousser l’utilisation à 100 %.

3) Should I just disable E-cores?

Parfois, pour des objectifs de latence très stricts, désactiver les E-cores (ou ne pas y placer votre service) peut simplifier la vie.
Mais vous jetez du débit et vous pouvez empirer le comportement énergétique d’autres façons. Préférez les cpusets et la politique d’abord ;
désactivez seulement si vous avez prouvé que l’ordonnancement hybride ne peut pas satisfaire vos SLOs avec un effort raisonnable.

4) Does Windows 11 really matter for hybrid CPUs?

Pour l’hybride Intel grand public, Windows 11 inclut des améliorations d’ordonnancement et une meilleure utilisation des indices matériels. Windows 10 peut fonctionner,
mais il est plus susceptible de mal placer les threads sous certains mélanges de charges avant/arrière. Si vous tenez à un comportement cohérent, standardisez.

5) On Linux, what’s the biggest lever I control?

La politique de placement CPU. Utilisez cgroups cpuset pour réserver les P-cores au travail sensible à la latence et contraindre le batch aux E-cores.
Ensuite validez la fréquence et le throttling. Le governor compte, mais le placement bouge généralement le curseur en premier.

6) Why did my throughput increase but my single-thread performance decrease?

Parce que la puissance du package est partagée. Allumer les E-cores peut réduire le budget de puissance disponible pour le boost des P-cores, donc la performance d’un seul thread diminue tandis que le débit global augmente.
Les systèmes hybrides échangent la vitesse par thread maximale contre le travail soutenu par watt.

7) How does SMT complicate hybrid planning?

Le SMT double les CPUs logiques sur les P-cores, ce qui gonfle les comptes de threads et pousse les frameworks à sursouscrire.
Pendant ce temps, les E-cores n’ont souvent pas SMT, donc « un CPU logique » peut signifier des capacités réelles différentes selon l’endroit où il atterrit.

8) What about containers and Kubernetes?

Si vous définissez des limites/requests CPU sans conscience de topologie, les pods peuvent atterrir sur n’importe quels CPUs logiques, y compris des E-cores.
Pour des pods sensibles à la latence, utilisez le labeling de nœud et les politiques cpuset/CPU manager quand approprié, et validez où vos pods s’exécutent.
Sinon vous vous retrouverez avec des « classes de performance aléatoires » dans un pool de nœuds supposé uniforme.

9) Do hybrid CPUs change how I do benchmarking?

Oui : vous devez rapporter le placement, la politique d’alimentation et les fréquences soutenues. Exécutez des tests en charge mixte, pas seulement des microbenchmarks isolés.
Faites toujours au moins une exécution épinglée sur P-cores et une sur E-cores pour connaître les bornes de comportement.

10) What’s the simplest “prove it” test for a suspected hybrid issue?

Épinglez une instance du service sur les P-cores (cpuset ou taskset), rejouez le même trafic et comparez p95/p99 et la fréquence CPU.
Si cela s’améliore, arrêtez de débattre des « régressions de code » et corrigez d’abord le placement/la politique de puissance.

Prochaines étapes à faire cette semaine

Le x86 hybride n’est pas un gadget ; c’est une réponse à la fin de l’échelle facile des fréquences et à la réalité des limites de puissance. Ça peut être excellent.
Ça peut aussi être un piège de performance si vous continuez à prétendre que les CPU sont symétriques.

  1. Cartographiez vos cœurs : produisez une fiche hôte listant les plages de CPUs logiques P-core et E-core. Mettez-la dans votre CMDB ou notes d’inventaire.
  2. Choisissez une politique : décidez quels workloads obtiennent des P-cores par défaut et lesquels sont autorisés sur les E-cores. R rendez-la explicite.
  3. Implémentez des cpusets : déployez-les comme partie des templates d’unités de service plutôt que des correctifs ad-hoc en astreinte.
  4. Instrumentez les signaux pertinents : utilisation par cœur, fréquence, événements de throttling, migrations/context switches, et latence de queue.
  5. Testez des scénarios mixés : faites toujours des benchmarks avec une activité d’arrière-plan réaliste, car c’est là que le comportement hybride apparaît.

Si vous faites ces cinq choses, les CPU hybrides cessent d’être mystérieux et commencent à être utiles. Vous n’avez pas besoin de devenir ingénieur ordonnanceur.
Il suffit d’arrêter de supposer que la puce ment quand elle fait exactement ce que vous lui avez implicitement demandé.

← Précédent
Slot 1 vs Socket 7 : la guerre des connecteurs qui a décidé votre prochain PC
Suivant →
E-mail « Adresse destinataire refusée » : pourquoi des utilisateurs valides rebondissent encore

Laisser un commentaire