IPC > GHz : l’explication la plus simple que vous retiendrez

Cet article vous a aidé ?

Vous l’avez vu : les achats choisissent « le CPU le plus rapide » parce que la fiche technique clame 3.8 GHz. Le service rame toujours, le p95 explose, et l’astreinte apprend la différence entre marketing et physique à 03:17.

Si vous ne retenez qu’une chose de cet article, que ce soit : le GHz indique la cadence du métronome. L’IPC indique la quantité de travail effectuée par battement. Votre charge utile vit dans la partie « travail ».

Le modèle en une phrase

Performance ≈ (fréquence d’horloge) × (IPC) × (nombre de cœurs utiles) − (attente sur mémoire, I/O, verrous et autres humains).

Le GHz est un multiplicateur. L’IPC en est un autre. Et le terme soustractif—attente—explique pourquoi votre « upgrade à 3.8 GHz » peut ne rien faire à part chauffer la pièce. Vous ne pouvez pas dépasser une faute de cache, une tempête de page fault ou un convoi de verrous par une fréquence plus élevée. En revanche, vous pouvez diagnostiquer ce pour quoi vous payez.

Ce qu’est réellement l’IPC (et ce que ce n’est pas)

IPC signifie instructions par cycle : en moyenne, combien d’instructions un CPU « retire » (termine) à chaque tick d’horloge. Si un cœur fonctionne à 3,5 GHz, cela fait 3,5 milliards de cycles par seconde. Si l’IPC est de 2,0, il retire environ 7 milliards d’instructions par seconde (approximativement ; la réalité a ses notes en bas de page).

Instructions retirées : le bac « terminé »

Les CPU modernes exécutent hors ordre. Ils fetchent, décodent et spéculent. Ils exécutent des instructions en parallèle, les réordonnent, et parfois jettent du travail si la spéculation s’est trompée. L’IPC fait généralement référence aux instructions retirées : celles qui ont traversé le pipeline et sont devenues réalité architecturale.

L’IPC n’est pas « l’intelligence du CPU »

L’IPC dépend de la charge de travail. Le même CPU peut afficher un IPC élevé pour des boucles de calcul serrées et un IPC médiocre pour des parcours de pointeurs dans la mémoire. Un autre CPU peut inverser la situation. C’est pour cela que benchmarker un microservice et extrapoler à « toute notre plateforme » mène souvent à un rack de regrets.

Une image mentale pratique

Pensez à un cœur CPU comme une cuisine de restaurant :

  • GHz est la fréquence à laquelle le chef envoie un clap pour signaler « étape suivante ».
  • IPC est le nombre de plats qui quittent le passe à chaque clap.
  • Latence cache/mémoire est le temps d’attente pour recevoir les ingrédients.
  • Mispredictions de branche sont quand le chef prépare le mauvais plat et le jette.
  • Verrous/contention sont les disputes autour de la poêle unique que tout le monde veut.

Accélérer les claps ne sert à rien si vous attendez toujours le camion de tomates.

Blague #1 : Acheter des CPU selon le GHz, c’est comme embaucher des barmen d’après la rapidité avec laquelle ils secouent un shaker vide.

Pourquoi le GHz vous trompe encore

La fréquence d’horloge est facile à imprimer sur une boîte. C’est aussi le nombre le moins stable dans un serveur moderne, car la fréquence est une trêve négociée entre limites d’alimentation, limites thermiques, règles de turbo et « ce qui se passe sur ce socket en ce moment ».

Turbo est conditionnel, pas permanent

Le « max turbo » affiché correspond souvent :

  • à un ou quelques cœurs,
  • pour une fenêtre temporelle limitée,
  • sous des conditions spécifiques de puissance et de température,
  • avec une charge qui ne déclenche pas un downclock (par exemple du code AVX intensif sur certaines architectures).

Si votre service utilise tous les cœurs sous charge (ce que la plupart font), ce qui vous importe est la fréquence soutenue sur tous les cœurs, pas le pic.

La fréquence peut baisser quand le travail devient « difficile »

Certaines combinaisons d’instructions consomment plus de puissance. Le code vectoriel peut réduire les fréquences. Le fait d’être chaud dans des racks denses peut aussi. De mauvaises options BIOS aussi. Le GHz n’est pas une propriété fixe ; c’est un résultat.

Et même si le GHz est élevé, l’IPC peut être bas

L’IPC bas arrive quand le cœur passe des cycles à autre chose qu’à retirer des instructions : attendre des fautes de cache, récupérer d’une mauvaise prédiction de branche, être bloqué par des dépendances, ou être limité par le front-end (incapable de fetcher/décoder assez vite).

Le graphique mental que vous devez garder

Imaginez une timeline CPU :

  • Retirement (bon) : les instructions se terminent.
  • Front-end bound : pas assez d’instructions sont fournies à l’exécution.
  • Back-end bound : les unités d’exécution ou le sous-système mémoire sont la limite.
  • Mauvaise spéculation : travail jeté à cause de mispredictions.

Un GHz élevé accélère la timeline. Il ne change pas quel compartiment domine.

Les quatre choses qui contrôlent l’IPC

Il existe de nombreux détails microarchitecturaux, mais vous pouvez garder l’IPC ancré avec quatre leviers principaux qui apparaissent en production.

1) La hiérarchie mémoire : les hits de cache sont le salaire

Un hit de cache est rapide ; la DRAM est lente ; le stockage est glaciaire. Votre IPC s’effondre quand le CPU attend les données. Les pires cas sont les charges de type parcours de pointeurs (hash tables, B-trees, graphes d’objets) où chaque étape dépend de la précédente.

La latence compte plus que la bande passante pour beaucoup de code serveur. Si vos accès aux données sont sérialisés, vous n’« utilisez pas toute la bande passante mémoire ». Vous attendez une seule chaîne de fautes.

2) Prédiction de branche : le CPU devine votre futur

Les CPU spéculent. Si le prédicteur de branche a raison, vous avez l’air d’un génie. S’il a tort, le pipeline est vidangé et vous payez en cycles. Un code avec beaucoup de branches imprévisibles peut plomber l’IPC même si les données sont chaudes en cache.

3) Parallélisme au niveau des instructions (ILP) : combien peut se passer en même temps

Les cœurs out-of-order peuvent exécuter plusieurs opérations par cycle si des instructions indépendantes sont prêtes. Les boucles serrées avec dépendances (par ex. un hachage itératif où chaque étape dépend de la précédente) limitent l’ILP. Vous verrez un IPC bas même si tout est en cache.

4) Le front-end : fetch/decodage est un goulot à part entière

Si le CPU ne peut pas alimenter le moteur d’exécution assez vite—à cause de misses I-cache, de problèmes de layout de code ou de limites de décodage d’instructions—l’IPC chute. Cela apparaît sur de gros binaires avec mauvaise localité, du code fortement indirect, du code JIT qui change souvent, ou des charges avec invalidations fréquentes du cache d’instructions.

Règle pratique : Si vous ne connaissez pas le goulot, supposez que c’est la latence mémoire ou la contention. Ces deux-là paient mon loyer.

IPC et charges réelles : BDD, web, stockage, JVM

Bases de données : « CPU-bound » signifie souvent « attente mémoire tout en tenant des verrous »

Les bases de données peuvent être gourmandes en calcul (compression, chiffrement, exécution de requêtes) mais sont souvent dominées par les schémas d’accès mémoire : recherches d’index, churn du buffer pool et structures riches en pointeurs. Un serveur BDD peut afficher 40–70% d’utilisation CPU et être quand même « limité par le CPU » parce que les threads chauds attendent et les autres sont inactifs ou bloqués.

Que faire : mesurer les stalls, les misses LLC et le temps de verrou. Si vous augmentez le GHz sans corriger le taux de cache miss, vous ne faites que rendre le CPU plus rapide pour attendre.

Services web : branchiness, allocations et latence sur la queue

Les handlers de requêtes ont beaucoup de branches : vérifications d’auth, routage, feature flags, sérialisation. Les pénalités de misprediction de branche apparaissent comme de la variance de latence tail. Ajoutez la pression du GC, et vous avez du temps CPU qui ne retire pas d’instructions utiles.

Que faire : chercher les mispredictions et problèmes de cache d’instructions, réduire les allocations. Si vous devez acheter du matériel, préférez des cœurs avec une forte performance par thread et un bon comportement de cache, pas simplement le turbo annoncé le plus élevé.

Chemins stockage/I/O : l’IPC est une victime, pas la cause

Les stacks de stockage bottleneck souvent sur des interruptions, des appels système, des switches de contexte et la contention de verrous dans le kernel ou le driver. Le CPU peut passer des cycles en mode noyau sans retirer beaucoup de travail applicatif. Les métriques d’IPC peuvent sembler bizarres parce que vous mesurez le mauvais « travail utile ».

Que faire : mesurer l’iowait, le temps softirq et les taux d’appels système. Ne « optimisez » pas en épinglant tout sur un cœur à moins d’aimer les surprises.

JVM et runtimes managés : le JIT peut augmenter l’IPC… jusqu’à ce qu’il ne le fasse plus

La compilation JIT peut produire des boucles serrées avec bonne localité et IPC élevé. Elle peut aussi produire des call sites mégamorphiques, des chemins déoptimisés et des safepoints fréquents qui transforment votre CPU en ordonnanceur. Si vous diagnostiquez, séparez « CPU dépensé à faire du travail » de « CPU dépensé à gérer le runtime ».

Une citation pour rester honnête : « L’espérance n’est pas une stratégie. » — Général Gordon R. Sullivan

Faits et historique que vous pouvez utiliser dans des débats

  • Les fréquences ont atteint un plafond au milieu des années 2000 à cause de la densité de puissance et des fuites ; l’industrie est passée de « horloges plus rapides » à « plus de cœurs » et « plus de travail par cycle ».
  • « NetBurst » (ère Pentium 4) poursuivait des GHz élevés avec des pipelines profonds ; il perdait souvent face à des conceptions à plus faible fréquence mais meilleur IPC, surtout sur du code réel.
  • L’exécution hors-ordre existe principalement pour améliorer l’IPC en exploitant le parallélisme au niveau des instructions ; c’est un ordonnanceur matériel fonctionnant à la fréquence du GHz.
  • Les prédicteurs de branche sont devenus sophistiqués parce que les mispredictions sont coûteuses ; des pipelines plus profonds amplifient le coût d’une mauvaise prédiction.
  • Les caches CPU ont grandi parce que la DRAM n’a pas suivi ; le « mur de la mémoire » est un thème récurrent en architecture.
  • L’IPC n’est pas portable entre jeux d’instructions ; comparer l’IPC entre x86 et ARM sans contexte est généralement dépourvu de sens car « une instruction » n’est pas une unité de travail uniforme.
  • La spéculation et la sécurité se sont heurtées à la fin des années 2010 (les failles de type Spectre) ; certaines atténuations peuvent réduire la performance en impactant la spéculation et le coût d’accès mémoire.
  • Les compteurs de performance existent depuis des décennies, mais « l’observabilité pour le hardware » est devenue courante dans les opérations lorsque l’efficacité des flottes et les coûts cloud ont forcé de meilleures mesures.

Fiche de diagnostic rapide

Ceci est le flux de travail « j’ai 30 minutes avant la conference d’incident ». L’objectif n’est pas une thèse. C’est d’identifier le goulot dominant et prendre une décision sûre.

Première étape : confirmez quel type de lenteur vous avez

  • Latence en hausse mais CPU faible ? Probablement attente : I/O, verrous, réseau ou stalls mémoire.
  • CPU saturé et débit plafonné ? Peut être lié au calcul, mais aussi aux spinlocks, tempêtes d’appels système ou GC.
  • Seule la latence tail est mauvaise ? Cherchez la contention, les pauses GC, les voisins bruyants, la throttling et le thrash du cache.

Deuxième étape : vérifiez la fréquence et le throttling

  • Le CPU tourne-t-il aux fréquences soutenues attendues ?
  • Des limites de puissance (PL1/PL2), du throttling thermique ou des quotas cgroup sont-ils en jeu ?

Troisième étape : mesurez si vous retirez du travail

  • Regardez l’IPC et les stalls via les compteurs de performance.
  • Si l’IPC est bas et les stalls élevés : la mémoire/branche/verrous sont probablement en cause.

Quatrième étape : décidez quel sous-système possède l’incident

  • iowait élevé / tâches bloquées → chemin stockage/réseau.
  • File exécutable élevée et commutation de contexte élevée → ordonnancement CPU/surabonnement.
  • Taux élevé de cache miss → localité des données, taille du working set ou placement NUMA.
  • Mauvaises prédictions de branche → imprévisibilité du chemin de code ou mauvais layout.

Cinquième étape : choisissez une action justifiable

Exemples : réduire la concurrence, déplacer un job bruyant, ajuster les quotas CPU, épingler la mémoire sur le nœud NUMA local, ou rollbacker un changement qui a augmenté le working set.

Tâches pratiques : commandes, sorties, décisions

Voici des tâches réelles à exécuter sous Linux. Chacune inclut ce que la sortie signifie et quelle décision en découle. Exécutez-les sur l’hôte affecté, pas sur votre laptop. La réalité est hostile à la théorie.

Task 1: See CPU model and advertised base/max

cr0x@server:~$ lscpu | egrep 'Model name|CPU MHz|CPU max MHz|CPU min MHz|Socket|Core|Thread|NUMA'
Model name:                         Intel(R) Xeon(R) Gold 6230 CPU @ 2.10GHz
CPU MHz:                            2095.123
CPU max MHz:                        3900.0000
CPU min MHz:                        800.0000
Socket(s):                          2
Core(s) per socket:                 20
Thread(s) per core:                 2
NUMA node(s):                       2

Sens : La machine affiche 3.9 GHz max, mais l’actuel est ~2.1 GHz. Cela peut être normal (horloge de base), ou indiquer un throttling sous charge.

Décision : Si les plaintes de performance coïncident avec un MHz actuel bas sous forte charge, passez aux vérifications du gouverneur de fréquence et du throttling.

Task 2: Watch real-time frequencies per core

cr0x@server:~$ sudo turbostat --quiet --interval 1 --num_iterations 5
     CPU     Avg_MHz   Busy%   Bzy_MHz   IRQ
       -       2240    62.14     3605   1123

Sens : Avg_MHz est la moyenne sur tous les cœurs ; Bzy_MHz est la fréquence quand le cœur est occupé. Ici, les cœurs occupés boostent à ~3.6 GHz.

Décision : Si Bzy_MHz est bien en dessous de l’attendu (ex. bloqué près de 2.1 GHz), suspectez des limites de puissance/throttling thermique, des réglages BIOS ou un downclock AVX.

Task 3: Check CPU governor (common on older configs and some cloud images)

cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
powersave

Sens : Le kernel tente d’économiser l’énergie, ce qui peut réduire la réactivité de la fréquence.

Décision : Sur des serveurs sensibles à la latence, mettre sur performance (après vérification de la politique). Si vous êtes dans un DC avec cap d’énergie, coordonnez-vous ; ne surprenez pas les Facilities.

Task 4: Check for cgroup CPU throttling (containers lie politely)

cr0x@server:~$ cat /sys/fs/cgroup/cpu.stat
usage_usec 983211234
user_usec 702112345
system_usec 281098889
nr_periods 12345
nr_throttled 9321
throttled_usec 551234567

Sens : nr_throttled et throttled_usec montrent que la charge a été fréquemment throttlée par des quotas CPU.

Décision : Si le throttling est significatif pendant la fenêtre d’incident, augmentez le quota/requests CPU ou réduisez la concurrence. Acheter du GHz ne résoudra pas un quota.

Task 5: Quick “is it CPU or waiting?” snapshot

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 6  0      0 812344  22044 912344    0    0     1     3 1800 4200 32  8 58  1  0
12  0      0 809112  22044 913008    0    0     0     0 2100 5200 44 11 45  0  0

Sens : r est le nombre de threads exécutables, b bloqués, split CPU user/system/idle/iowait. Un wa faible suggère que vous n’êtes pas bloqué par le stockage.

Décision : Si r est constamment supérieur au nombre de cœurs et que id est faible, vous êtes CPU-saturé ou fortement contentieux. Mesurez alors l’IPC/les stalls.

Task 6: Check run queue and load relative to cores

cr0x@server:~$ uptime
 10:41:22 up 23 days,  4:12,  2 users,  load average: 38.12, 41.03, 39.77

Sens : Une load average proche ou supérieure au nombre de cœurs indique de nombreuses tâches exécutables ou non interruptibles.

Décision : Si la charge est élevée mais que le CPU est inactif, suspectez un I/O bloqué ou de la contention mutex. Associez avec vmstat et pidstat.

Task 7: Identify hot processes and whether time is user vs kernel

cr0x@server:~$ pidstat -u -p ALL 1 3
Linux 6.2.0 (server)  01/10/2026  _x86_64_  (80 CPU)

#      Time   UID       PID    %usr %system  %CPU  Command
10:41:40  1001    21433   520.00   80.00 600.00  java
10:41:40     0     1321    10.00  120.00 130.00  ksoftirqd/12

Sens : La JVM consomme beaucoup de CPU utilisateur ; ksoftirqd indique un traitement intense de soft interrupts (souvent réseau).

Décision : Si ksoftirqd est chaud, regardez les taux de paquets réseau, la distribution des IRQ et les réglages NIC. Si le temps utilisateur domine, regardez l’IPC et les chemins de code.

Task 8: Measure IPC quickly with perf (system-wide)

cr0x@server:~$ sudo perf stat -a -e cycles,instructions,branches,branch-misses,cache-references,cache-misses -- sleep 10
 Performance counter stats for 'system wide':

    38,221,456,789      cycles
    41,002,112,334      instructions              #    1.07  insn per cycle
     7,991,122,010      branches
       211,334,556      branch-misses             #    2.64% of all branches
     2,114,334,221      cache-references
       322,114,990      cache-misses              #   15.23% of all cache refs

      10.001234567 seconds time elapsed

Sens : IPC ~1.07 système global. Taux de miss de branche ~2.6% (pas terrible). Le ratio de cache miss est notable.

Décision : IPC un peu bas plus des cache misses significatifs suggèrent des problèmes de localité/working set. Ne poursuivez pas le GHz ; traquez les misses, le layout des données, NUMA et la contention.

Task 9: Measure IPC for one process (useful during an incident)

cr0x@server:~$ sudo perf stat -p 21433 -e cycles,instructions -- sleep 10
 Performance counter stats for process id '21433':

    12,112,334,990      cycles
    10,001,223,110      instructions              #    0.83  insn per cycle

      10.000998321 seconds time elapsed

Sens : Ce processus retire <1 instruction par cycle en moyenne. C’est beaucoup d’attente ou du travail difficilement parallélisable.

Décision : Si l’app est censée être calcul-intensive, cela indique des stalls (mémoire, verrous, syscalls, branches). Passez à l’analyse top-down et aux flame graphs si possible.

Task 10: Spot major faults and page-fault storms (they murder IPC)

cr0x@server:~$ pidstat -r -p 21433 1 3
#      Time   UID       PID  minflt/s  majflt/s     VSZ     RSS  %MEM  Command
10:42:20  1001    21433   12000.00      0.00 18432324 9321120  28.3  java
10:42:21  1001    21433   11500.00      3.00 18432324 9325540  28.3  java

Sens : Les minor faults élevés peuvent être normaux (ex. fichiers mappés en mémoire), mais les major faults signifient des page-ins sur disque. C’est de la latence, qui devient des stalls CPU.

Décision : Si les major faults augmentent pendant des pics de latence, étudiez la pression mémoire, le comportement THP et le churn du cache fichier ; ajoutez de la RAM ou réduisez le working set.

Task 11: Check NUMA balance and remote memory access (hidden latency)

cr0x@server:~$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0-39
node 0 size: 192000 MB
node 0 free: 81234 MB
node 1 cpus: 40-79
node 1 size: 192000 MB
node 1 free: 23456 MB

Sens : Deux nœuds NUMA ; le nœud 1 est beaucoup plus alloué. Le déséquilibre peut impliquer des accès mémoire distants.

Décision : Si un seul processus s’étend sur sockets mais sa mémoire n’est pas locale, épinglez CPU/mémoire ou corrigez le placement via le scheduler. La mémoire distante est une taxe que vous payez en IPC.

Task 12: Confirm if transparent huge pages are causing latency variance

cr0x@server:~$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

Sens : THP est réglé sur always. Cela peut aider le débit mais parfois détériore la latence tail à cause de bloquages de compactage.

Décision : Pour des bases de données sensibles à la latence, envisagez madvise ou never après tests. Changez prudemment ; c’est un levier de politique, pas une superstition.

Task 13: Check for CPU steal time (cloud reality check)

cr0x@server:~$ mpstat 1 3
Linux 6.2.0 (server)  01/10/2026  _x86_64_  (8 CPU)

10:43:10 AM  all   %usr %nice %sys %iowait %irq %soft %steal %idle
10:43:11 AM  all   41.00  0.00  9.00    0.00 0.00  1.00   8.00 41.00

Sens : %steal montre le temps où votre VM voulait du CPU mais que l’hyperviseur ne vous a pas planifié. Cela peut ressembler à un « IPC bas » parce que vous n’êtes pas exécuté.

Décision : Si le steal est élevé pendant les incidents, changez de type d’instance, évitez les hôtes surcommittés ou négociez le placement. Ne refactorez pas votre code pour corriger le voisin bruyant d’autrui.

Task 14: Check disk I/O latency quickly (because storage can impersonate CPU)

cr0x@server:~$ iostat -x 1 3
Linux 6.2.0 (server)  01/10/2026  _x86_64_  (80 CPU)

Device            r/s     w/s   r_await   w_await  aqu-sz  %util
nvme0n1         120.0   450.0     2.10     8.40    4.20   96.00

Sens : Un %util élevé et des await relevés indiquent que le device est saturé ou en file d’attente. Les threads bloquent, le CPU s’endort ou fait des context switches, et votre rêve d’upgrade CPU meurt doucement.

Décision : Si l’await stockage concorde avec les pics de latence, corrigez l’I/O : réduisez les écritures sync, ajustez les queues, ajoutez des devices, ou séparez les workloads.

Task 15: Confirm interrupt distribution (IRQ storms reduce useful IPC)

cr0x@server:~$ grep -E 'eth0|nvme' /proc/interrupts | head
  64:  99112233   0   0   0  IR-PCI-MSI 524288-edge  eth0-TxRx-0
  65:    112233   0   0   0  IR-PCI-MSI 524289-edge  eth0-TxRx-1
  66:     99887   0   0   0  IR-PCI-MSI 524290-edge  eth0-TxRx-2

Sens : Les IRQ tombent sur un seul CPU (première colonne) tandis que d’autres montrent zéro. C’est un hotspot, souvent générateur de softirq et de latence.

Décision : Corrigez l’affinité IRQ / politique RPS/XPS et assurez-vous que les queues NIC sont distribuées. Si vous laissez, vous augmenterez les cœurs et bottleneckerez toujours sur CPU0.

Task 16: Check memory bandwidth vs latency pressure (quick heuristic)

cr0x@server:~$ sudo perf stat -a -e cpu/mem-loads/,cpu/mem-stores/ -- sleep 5
 Performance counter stats for 'system wide':

       882,112,334      cpu/mem-loads/
       401,122,110      cpu/mem-stores/

       5.000912345 seconds time elapsed

Sens : Des comptes de load/store élevés peuvent suggérer un comportement intensif mémoire ; associez avec les métriques de cache-miss pour inférer si ces opérations touchent surtout le cache ou vont vers la DRAM/distante.

Décision : Si les ops mémoire sont élevées et l’IPC bas, vous avez probablement un service lié à la mémoire. Favorisez des CPU avec caches plus grands, meilleur préfetch et un sous-système mémoire plus efficace, pas seulement du GHz.

Trois mini-histoires du monde de l’entreprise

1) Incident causé par une mauvaise hypothèse : « plus de GHz = API plus rapide »

Une société SaaS de taille moyenne avait une API de checkout qui ralentissait à chaque campagne marketing. L’équipe a signalé une saturation CPU sur la couche applicative. Les achats ont proposé : upgrade vers des CPU « plus rapides » avec des fréquences annoncées plus élevées. La migration a été planifiée, les tableaux de bord approuvés, et tout le monde s’attendait à une victoire.

Après le cutover, l’utilisation moyenne CPU a légèrement baissé. La latence, non. La latence tail a empiré. Le postmortem a commencé par une diapositive gênante : « On a acheté des pièces 3.9 GHz, pourquoi sommes-nous plus lents ? »

Ils ont fini par mesurer l’IPC et les cache misses. Les nouveaux CPU avaient des turbos plus hauts mais un cache last-level par cœur plus petit et une topologie mémoire différente. Leur service était dominé par des stalls causés par des cache misses provenant d’un grand catalogue produit en mémoire et d’un tas de feature flags. L’IPC est tombé sous charge parce que le working set débordait plus souvent du cache, et le sous-système mémoire était plus occupé.

La correction fut peu glamour : réduire le working set (supprimer les flags morts, compresser les structures de données chaudes), améliorer la localité (stocker les IDs de façon contiguë, éviter les maps lourds en pointeurs), et épingler les processus les plus chauds à la mémoire NUMA locale. Le matériel n’était pas « mauvais ». L’hypothèse l’était.

Ils ont gardé les machines, mais les ont réaffectées à des jobs batch où la fréquence aidait. La flotte checkout est passée à des CPU avec un cache plus grand et une meilleure performance soutenue tous-cœurs, pas le turbo le plus élevé en sticker.

2) Optimisation qui a mal tourné : « Épinglons tout pour meilleure localité de cache »

Une autre organisation gérait un service d’ingestion de logs sensible à la latence. Quelqu’un a remarqué que les migrations CPU étaient élevées lors des pics. Ils ont décidé d’épingler agressivement les threads d’ingestion principaux à un sous-ensemble de cœurs via des cpusets, espérant améliorer la localité du cache et réduire le context switching.

Pendant un jour, les graphes se sont améliorés : moins de migrations, latence moyenne légèrement inférieure. Puis un changement de trafic est survenu. Un nouveau client a envoyé des payloads plus larges, augmentant les coûts de parsing et les allocations mémoire. Les cœurs épinglés ont atteint 100% d’utilisation alors que le reste du système restait sous-utilisé. La latence tail a grimpé, et l’arriéré a augmenté.

La racine du problème n’était pas « GHz insuffisant ». C’était de la starvation d’ordonnancement auto-infligée. L’épinglage a retiré la capacité du kernel à répartir la charge, et a aussi concentré les interruptions et le travail kernel sur les mêmes cœurs. L’IPC sur les cœurs épinglés a chuté car ils passaient plus de temps en chemins noyau et en attente mémoire pour les payloads plus gros.

La solution a été d’épingler seulement ce qui devait l’être (quelques threads sensibles), distribuer correctement les IRQ, et laisser de la marge pour la variabilité. Ils ont aussi introduit du backpressure et limité la concurrence par connexion pour éviter de transformer des stalls CPU en effondrement de file d’attente.

Blague #2 : Épingler des CPU c’est comme se tatouer le numéro de siège à l’aéroport : ça rassure jusqu’au changement de porte d’embarquement.

3) Pratique ennuyeuse mais correcte qui a sauvé la mise : « Mesurer avant d’agir »

Une équipe fintech gérait un cluster OLTP avec des SLOs stricts. Lors d’un test de charge trimestriel, la latence p99 a augmenté de 40% sur un shard. L’impulsion initiale fut de monter la taille des instances et passer à autre chose. Au lieu de cela, l’astreinte a suivi un runbook ennuyeux : capturer les compteurs de base, confirmer la fréquence, vérifier le throttling, valider la localité NUMA, puis inspecter l’I/O.

Ils ont constaté que la fréquence CPU était correcte. L’IPC était correcte. Les cache misses stables. Mais l’iowait avait augmenté pendant la même fenêtre. iostat montrait une latence d’écriture élevée et une forte utilisation du device. Le shard était sur un hôte où une autre charge bruyante saturait le même NVMe. Ce n’était pas un problème CPU.

La pratique « ennuyeuse » était simple : capture obligatoire de perf stat, vmstat et iostat pendant les incidents, stockées avec horodatage. Cela a rendu le pattern évident et a évité un upgrade CPU coûteux et erroné.

Ils ont corrigé en isolant le stockage pour la BDD et en ajustant la planification pour que les voisins bruyants ne partagent pas les devices. Le test de charge a réussi sur la même classe CPU. Personne n’a reçu de trophée, mais le SLO est resté vert, et c’est le seul trophée qui compte.

Erreurs fréquentes (symptôme → cause racine → correction)

1) « Le CPU est à 60%, donc nous ne sommes pas CPU-bound »

Symptôme : Latence élevée, CPU pas saturé, les threads s’accumulent.

Cause racine : Quelques threads chauds sont bloqués sur la mémoire/les verrous tandis que d’autres cœurs sont inactifs ; l’utilisation globale masque les goulots par thread.

Correction : Utiliser le profilage par thread et les compteurs perf ; réduire la contention ; améliorer la localité des données ; limiter la concurrence pour éviter l’engorgement.

2) « Nous avons besoin de GHz plus élevés »

Symptôme : Débit plafonné ; les achats proposent des SKU « horloge plus rapide ».

Cause racine : L’IPC est bas dû aux cache misses, mispredicts de branche, appels système ou overhead runtime. La fréquence n’est pas le multiplicateur limitant.

Correction : Mesurer l’IPC et les taux de miss ; optimiser les chemins chauds ; choisir des CPU avec cache et mémoire adaptés à la charge.

3) « Turbo dit 4.2 GHz, donc nous avons 4.2 GHz »

Symptôme : Benchmarks très variables entre runs ; production plus lente que les tests dev.

Cause racine : Le turbo est opportuniste ; la fréquence soutenue tous-cœurs est plus basse sous charge réelle ; les limites de puissance/thermiques changent le comportement.

Correction : Mesurer Bzy_MHz sous charge représentative ; revoir les limites BIOS ; assurer le refroidissement ; éviter d’évaluer les CPU sur des microbenchmarks single-thread uniquement.

4) « Nous avons optimisé en épinglant les threads, maintenant c’est pire »

Symptôme : Latence moyenne améliorée mais tail et arriérés empirent après un changement de forme de trafic.

Cause racine : L’épinglage excessif réduit la flexibilité du scheduler et concentre les interruptions ; les optimisations locales créent de la starvation globale.

Correction : Épingler avec parcimonie ; distribuer les IRQ ; laisser des cœurs libres ; valider sous plusieurs patterns de trafic.

5) « Notre CPU est lent dans le cloud »

Symptôme : CPU occupé mais rendement faible ; pics de latence périodiques.

Cause racine : Steal time, throttling, ou voisins bruyants ; vous n’êtes pas réellement exécuté quand vous le pensez.

Correction : Vérifier %steal et les stats de throttling cgroup ; choisir d’autres familles d’instances ; utiliser des hôtes dédiés si besoin.

6) « L’IPC est bas, donc le CPU est mauvais »

Symptôme : perf montre un IPC <1 et la panique s’installe.

Cause racine : La charge est liée à la latence mémoire (pointer chasing), ou la mesure couvre du temps noyau non pertinent pour le progrès applicatif.

Correction : Mesurer par processus, corréler avec les cache misses et la répartition des stalls, et envisager des changements d’algorithme/structure de données avant de blâmer le silicium.

7) « Nous avons upgradé le CPU et sommes devenus plus lents »

Symptôme : Régressions matérielles sur workload réel.

Cause racine : Différences de taille de cache, topologie NUMA, vitesses mémoire, ou comportement microarchitectural ; aussi possibles changements de valeurs par défaut BIOS.

Correction : Re-tuner NUMA, réglages BIOS et paramètres kernel ; re-baseliner les compteurs perf ; valider avec des tests de charge réalistes.

Listes de contrôle / plan pas à pas

Lors du choix de CPU (ou type d’instance) : quoi faire et quoi éviter

  1. Classifiez la charge : compute-bound, memory-latency-bound, memory-bandwidth-bound, I/O-bound, ou contention-bound. Si vous ne savez pas, mesurez.
  2. Utilisez des benchmarks représentatifs : votre service réel, formes de données réelles, concurrence réelle, réglages GC réels. Les tests synthétiques suffisent pour une sanity check, pas pour acheter.
  3. Comparez le comportement soutenu tous-cœurs : mesurer sous charge 10–30 minutes, pas 30 secondes de gloire turbo.
  4. Vérifiez le cache par cœur : surtout pour les services en mémoire et les bases de données. Le cache vaut souvent davantage que +300 MHz.
  5. Validez l’ajustement NUMA : la charge tient-elle sur une seule socket ? Sinon, planifiez la localité mémoire et les coûts d’interconnexion.
  6. Prévoyez les atténuations de sécurité : assurez-vous de comparer des systèmes dans le même état de kernel et microcode.
  7. Recherchez le risque de throttling : power capping, racks denses, crédits CPU cloud, quotas cgroup.
  8. Évitez d’acheter sur le GHz de pointe : préférez la performance par cœur publiée en conditions soutenues et vos propres baselines IPC/compteurs.

Pendant un incident : workflow minimal et sûr

  1. Capturez vmstat 1 5, mpstat 1 3, iostat -x 1 3.
  2. Vérifiez le throttling : cgroups, fréquence et steal time.
  3. Mesurez l’IPC rapidement avec perf stat (système et PID chaud).
  4. Décidez : CPU calcul vs stalls mémoire vs I/O vs contention. Choisissez une cause.
  5. Prenez une action réversible : réduire la concurrence, déplacer un workload bruyant, ajuster un quota, ou rollbacker le changement ayant élargi le working set.
  6. Notez les compteurs et la fenêtre temporelle. Le vous du futur en aura besoin.

Après l’incident : rendre la prochaine fois moins coûteuse

  1. Créez un tableau de bord baseline : proxy IPC (instructions/cycle), cache misses, context switches, major faults, iowait, steal time.
  2. Codifiez le runbook avec commandes et « à quoi ressemble le bon état ».
  3. Effectuez un test trimestriel « réalité matérielle » : fréquences soutenues, thermiques et vérifs de throttling sous charge.
  4. Apprenez à l’équipe achats une phrase : « performance soutenue tous-cœurs avec compteurs workload ». Répétez jusqu’à obtention des fonds.

FAQ

1) Quel est un « bon » nombre d’IPC ?

Ça dépend du CPU et de la charge. Beaucoup de services réels tournent autour de ~0.5–2.0 IPC. Des boucles de calcul serrées peuvent monter plus haut. Le pointer-chasing peut être plus bas. La tendance compte : si l’IPC a chuté après un déploiement, quelque chose a changé dans le comportement (working set, branches, syscalls, verrous).

2) Si l’IPC est bas, dois-je changer de CPU ?

Généralement non. Un IPC bas signifie souvent que vous attendez la mémoire, l’I/O ou que vous avez de la contention. Un « meilleur CPU » aide s’il a un sous-système mémoire plus fort, des caches plus grands ou une meilleure prédiction de branche pour votre code. Mais le premier gain vient souvent du logiciel : réduire les misses, réduire les verrous, réduire les allocations.

3) Pourquoi les benchmarks montrent-ils de gros gains avec un GHz plus élevé alors que la production ne suit pas ?

Les benchmarks tiennent souvent dans le cache, s’exécutent en mono-thread et évitent I/O et contention. La production a des working sets plus grands, plus de branches, plus d’appels système, plus d’interruptions et des voisins. Le GHz aide quand le CPU est le facteur limitant, pas quand il attend.

4) Plus de cœurs bat-il un IPC plus élevé ?

Seulement si votre charge scale proprement. Beaucoup de services sont limités par des ressources partagées : verrous, connexions BDD, bande passante mémoire, ou une file unique. Si le scaling cale à 16 threads, acheter 64 cœurs ne résoudra pas. Une meilleure performance par cœur (IPC plus élevé) peut être un meilleur investissement.

5) L’IPC est-il comparable entre Intel et AMD ? Entre x86 et ARM ?

Entre CPU d’une même ISA et d’une même époque, comparer l’IPC peut être utile. Entre ISAs différentes, c’est hasardeux car le mix d’instructions diffère. Utilisez des benchmarks bout en bout et des compteurs pour comprendre pourquoi, plutôt que de traiter l’IPC comme un score universel.

6) Comment la taille du cache se rapporte-t-elle à l’IPC ?

Plus de cache peut améliorer l’IPC en transformant des accès DRAM en hits cache. Mais ce n’est pas que la taille : la latence, l’associativité, le prefetch et la topologie core-cache comptent. Pour beaucoup de workloads serveurs, la last-level cache par cœur est une spécification critique.

7) Un déploiement peut-il changer l’IPC sans beaucoup changer l’utilisation CPU ?

Oui. Vous pouvez garder le CPU à 60% et être plus lent si la nouvelle version augmente le working set, provoque plus de cache misses, ajoute des branches, augmente les appels système ou introduit de la contention. L’utilisation CPU est un instrument grossier ; IPC et indicateurs de stalls vous disent ce que ce temps CPU a accompli.

8) « Le GHz n’a pas d’importance » est-il la bonne conclusion ?

Non. Le GHz compte quand vous êtes vraiment lié au calcul et que vous retirez efficacement des instructions. Le point est que le GHz n’est pas suffisant, et souvent pas stable. Traitez la fréquence comme une variable et validez avec des compteurs et des tests réels.

9) Quelle est la manière la plus rapide d’expliquer l’IPC à un interlocuteur non technique ?

« La vitesse d’horloge indique à quelle fréquence le CPU tic-tac. L’IPC indique la quantité de travail réalisée par tic. Notre service est limité par l’attente, pas par la rapidité des tics. »

Conclusion : prochaines étapes que vous ferez vraiment

Si vous ne changez qu’une habitude : arrêtez de traiter le GHz comme une garantie de performance. Commencez à le considérer comme une variable.

Faites ceci ensuite :

  1. Choisissez un service critique et capturez une baseline sous charge typique : turbostat, perf stat, vmstat, iostat et stats de throttling cgroup.
  2. Notez trois chiffres qui comptent : MHz busy soutenu, IPC et ratio de cache miss. Vous avez maintenant une empreinte.
  3. Quand la performance régresse, comparez les empreintes avant de débattre du hardware. Si l’IPC a chuté, trouvez l’attente. Si le MHz a baissé, trouvez le throttle. Si les deux vont bien, cherchez ailleurs (I/O, verrous, réseau).
  4. Quand il faut acheter du matériel, achetez-le pour le goulot mesuré : cache et comportement mémoire pour services liés mémoire ; fréquence soutenue pour les charges compute-bound ; et ordonnancement prévisible pour le travail sensible à la latence.

Vous n’avez pas besoin de devenir architecte CPU. Il vous suffit d’arrêter d’être surpris par les mêmes goulots. L’IPC est le moyen le plus rapide d’arrêter de vous faire avoir par un grand chiffre GHz en petit caractère.

← Précédent
Échec de la négociation TLS SMTP : corriger correctement certificats, suites et chaînes
Suivant →
Goulets d’étranglement sans hystérie : mesurer la limite réelle

Laisser un commentaire