Évolution de Zen : ce qui change entre générations et que vous ressentez vraiment

Cet article vous a aidé ?

Vous ne « ressentez » pas une nouvelle génération de CPU parce qu’une capture de benchmark est plus jolie. Vous la sentez quand la latence p99 cesse de monter en flèche à 10:03 tous les jours, quand vos nœuds de stockage arrêtent de prendre du retard sur les scrubs, quand votre facture d’électricité ne croit plus plus vite que vos effectifs, et quand votre canal d’incidents redevient ennuyeux.

Les évolutions Zen — de Zen 1 à Zen 4, et la variante Zen 4c — regorgent de changements invisibles sur les slides marketing et terriblement évidents en production. Voici la visite pratique : ce qui change réellement entre les générations, comment cela se manifeste dans de vrais systèmes, et comment le prouver avec des commandes plutôt qu’avec des impressions.

Ce que vous ressentez vraiment : les deltas visibles en production

La plupart des équipes achètent des CPU comme elles achètent des parapluies : en fonction de l’humidité qu’elles ont subie la dernière fois. C’est compréhensible, mais cela mène à de mauvaises attentes. Entre les générations Zen, les changements que vous ressentez se regroupent en cinq catégories :

1) Le comportement de la latence tail change

Zen n’est pas seulement « plus d’IPC ». La disposition des caches change, les complexes de cœurs évoluent, la vitesse du fabric change, et les contrôleurs mémoire changent. Ces éléments modifient la forme des distributions de latence. Le grand « ressenti » de Zen 3 pour beaucoup de services sensibles à la latence était que la communication inter-cœurs devenait moins étrange parce que la frontière CCX a bougé (plus bas). Zen 4 donne souvent l’impression de « pareil, mais plus rapide », jusqu’à ce que vous remarquiez que la mémoire et le PCIe peuvent devenir le nouveau plafond.

2) Les plafonds de bande passante bougent (et les goulots aussi)

Sur des plateformes plus anciennes, vous pouvez être limité par le CPU. Sur des plateformes plus récentes, vous pouvez devenir lié par la mémoire ou par les E/S sans toucher au code. Lorsque PCIe 5 arrive, les pipelines de stockage peuvent passer de « le PCIe est la limite » à « votre firmware NVMe, les réglages IOMMU ou l’affinité IRQ sont la limite ». Les montées de version révèlent quelle partie de votre pile est la plus mauvaise menteuse.

3) La densité de cœurs change tout opérationnellement

Un nombre de cœurs plus élevé ne signifie pas seulement un débit supérieur. Cela signifie plus de sensibilité NUMA, plus de contention pour les caches partagés, plus de décisions de routage d’interruptions, et plus de façons de se faire mal avec un réglage kernel naïf « universel ». La différence entre « CPU rapide » et « système rapide » dépend de la pertinence de vos décisions conscientes de topologie.

4) L’alimentation et le thermique cessent d’être du bruit de fond

Le rapport performance/watt est là où Zen est devenu brutal au centre de données. Mais des comportements turbo plus élevés et des sockets plus denses font de « refroidissement » une donnée d’ingénierie, pas une réflexion tardive des facilities. Si vous avez déjà vu un nœud se brider sous un test de charge soutenu puis bien se comporter en prod, vous avez rencontré ce problème.

5) La maturité du firmware et du microcode compte plus que vous ne le souhaitez

Les nouvelles plateformes sortent avec une « personnalité en début de vie ». Ça s’améliore. Votre métier est de traiter le BIOS, l’AGESA et le microcode comme des dépendances de production. Si ça vous semble ennuyeux, oui. Aussi : c’est moins cher que le downtime.

Une citation pour rester honnête, de Gene Kranz : « Failure is not an option. » Cette phrase est souvent répétée ; traitez-la comme une idée paraphrasée sur la rigueur sous pression, pas comme un slogan de performance.

Blague #1 : Mettre à niveau les CPU pour corriger un problème d’architecture, c’est comme acheter une imprimante plus rapide pour améliorer votre écriture manuscrite.

Faits et contexte qui expliquent les points étranges

Vous prendrez de meilleures décisions si vous vous souvenez de quelques faits concrets sur la façon dont on en est arrivé là :

  1. Zen (2017) était le « reset » d’AMD après l’ère Bulldozer, ramenant des cœurs à fort IPC et réintégrant la concurrence sérieuse sur les serveurs.
  2. EPYC “Naples” (Zen 1) utilisait une approche MCM multi-die ; la topologie était puissante mais facile à mal configurer pour des charges sensibles au NUMA.
  3. Zen 2 (2019) est passé aux chiplets : chiplets CPU en 7 nm plus un die I/O. Cette séparation est fondamentale pour la plupart de ce que vous vivrez ensuite (surtout le comportement mémoire/E/S).
  4. Zen 3 (2020) a réorganisé les cœurs et le cache en un complexe de 8 cœurs unifié par CCD, réduisant certaines pénalités cross-core/cache et rendant « un thread qui parle à un autre thread » moins coûteux.
  5. Zen 4 (2022) a introduit le DDR5 et le PCIe 5 sur les plateformes EPYC grand public, repoussant le front des goulots et exposant les tuyaux I/O négligents.
  6. Les variantes 3D V-Cache ont modifié la conversation sur le tuning : vous pouvez acheter du cache au lieu d’espérer une amélioration de la latence mémoire. C’est un compromis que vous devriez quantifier réellement.
  7. Les mitigations de sécurité (ère Spectre et suivantes) ont changé les valeurs par défaut du kernel et le comportement des hyperviseurs ; les comparaisons génération-à-génération sans contexte de mitigations sont souvent de la fiction.
  8. Linux a appris la topologie au fil du temps. Les améliorations de l’ordonnanceur et du NUMA balancing signifient que « même matériel, noyau différent » peut ressembler à un changement de génération.
  9. La vitesse de l’Infinity Fabric et sa relation aux horloges mémoire ont été un thème récurrent ; cela influence la latence inter-die et explique pourquoi la configuration mémoire n’est pas une simple case à cocher.

Zen par génération : les changements qui comptent pour l’exploitation

Je vais être un peu injuste avec les noms marketing et me concentrer sur ce qui vous réveille à 2 h du matin. Le « ressenti » de chaque génération combine conception des cœurs, cache, mémoire, E/S et maturité de la plateforme.

Zen 1 / Zen+ (ère Naples) : « C’est rapide, mais la topologie vous fera mal si vous faites comme chez Intel »

Les serveurs Zen 1 ont été un choc sur le marché : beaucoup de cœurs, beaucoup de lanes, un bon rapport performance/prix. Ils ont aussi introduit beaucoup d’équipes à la réalité que NUMA n’est pas une théorie. Naples pouvait se comporter comme plusieurs machines soudées ensemble si vous ne faisiez pas attention à la population mémoire et au placement des processus.

Ce que vous ressentez : latence tail imprévisible sous bavardage cross-socket ou cross-die, et des charges qui évoluent jusqu’à un point puis chutent brutalement.

Que faire : apprenez vos nœuds NUMA, épinglez les services critiques, et cessez de prétendre que « répartir sur tous les cœurs » est toujours bon.

Zen 2 (Rome) : « Chiplets, meilleur scaling, et moins de surprises — sauf si vous saturez la mémoire »

Zen 2 a rendu l’architecture chiplet dominante sur les serveurs. Le die I/O a centralisé les contrôleurs mémoire et les E/S. Cela a souvent rendu la plateforme plus facile à comprendre, mais cela a aussi fait de la bande passante mémoire une ressource partagée que vous pouvez brûler plus vite avec un grand nombre de cœurs.

Ce que vous ressentez : meilleure performance par cœur et montée en charge plus lisse ; mais les charges intensives en mémoire commencent à montrer que « la bande passante est le nouveau CPU ».

Que faire : considérez les canaux mémoire comme une capacité de première classe. « Plus de DIMM » peut être une décision de performance, pas seulement de capacité.

Zen 3 (Milan) : « CCX unifié : la latence cesse d’être ‘mystérieuse’ pour beaucoup de charges »

Le grand gain opérationnel de Zen 3 est que, dans un CCD, les cœurs partagent un L3 unifié plutôt que de plus petits partitions CCX. Cela réduit certaines pénalités quand des threads partagent des données mais sont sur des cœurs différents.

Ce que vous ressentez : améliorations p99 pour les services qui ont beaucoup d’état partagé en lecture (caches, tables de routage, certains workloads JVM), plus moins de cas « pourquoi déplacer le process sur un autre core change la latence ? »

Que faire : revoyez les anciennes règles de pinning. Certains hacks nécessaires sur Zen 1/2 deviennent inutiles — ou nuisibles.

Zen 4 (Genoa) : « DDR5 et PCIe 5 déplacent les bornes ; alimentation, firmware et tuning I/O deviennent plus audibles »

La vraie histoire de Zen 4 est la plateforme : DDR5, PCIe 5 et des comptes de cœurs supérieurs. Si vous faites du stockage, du réseau ou quoi que ce soit qui consiste essentiellement à « déplacer des octets sans bloquer », vous le sentirez.

Ce que vous ressentez : marge de débit et capacité de consolider davantage de charges par socket — jusqu’à ce que la gestion des interruptions, les réglages IOMMU, ou la sensibilité à la latence mémoire rattrapent votre configuration.

Que faire : prévoyez du temps pour le tuning BIOS/firmware et l’alignement IRQ/NUMA. Aussi : attendez-vous à des bizarreries de plateforme au début. Planifiez des fenêtres de patches.

Zen 4c (variantes cœurs denses) : « Plus de cœurs, comportement par cœur légèrement différent ; le choix d’ordonnancement compte »

Les variantes cœurs denses existent pour maximiser le débit par unité de rack et par watt. Le « ressenti » est que vous pouvez compacter plus de travail, mais vous devez être plus délibéré sur quels services s’y placent (orientés débit, moins sensibles à la latence) plutôt que sur des pièces à fréquence plus élevée.

Ce que vous ressentez : fort débit pour les jobs parallèles, mais certains composants mono-thread ou sensibles à la latence peuvent nécessiter isolation ou des SKU différents.

Que faire : séparez « tier latence » et « tier débit » dans la planification de capacité. Ne les mélangez pas par commodité.

Topologie, NUMA, CCD/CCX : où la performance se cache

Si vous voulez un modèle mental qui explique la plupart des « bizarreries Zen », c’est celui-ci : votre CPU n’est pas un monolithe. C’est un quartier de petites îles de calcul reliées par des routes. Certaines routes sont rapides. D’autres s’embouteillent. Votre travail est de garder les voisins bavards proches.

Ce qui a changé entre les générations Zen

  • Zen 1/2 : des domaines de cache plus petits signifiaient plus de misses cross-domain pour des jeux de travail partagés, ce qui se manifestait par des pics de latence quand le placement des threads changeait.
  • Zen 3 : L3 unifié par CCD a réduit la pénalité pour « deux threads partagent des données mais ne partagent pas une tranche de cache ». C’est un changement pratique et mesurable.
  • Zen 4 : les améliorations de plateforme élèvent les plafonds, mais la complexité de la topologie augmente. Le nombre de cœurs monte, les canaux mémoire changent, et vous pouvez avoir plus de nœuds NUMA selon le BIOS et le SKU.

Pourquoi les SRE doivent s’en soucier

Les décisions de topologie apparaissent comme :

  • Dérive de latence p95/p99 quand le kernel migre des threads à travers des cœurs/nœuds NUMA.
  • Utilisation CPU inégale (un nœud NUMA chaud, d’autres inactifs) parce que la localité mémoire pilote le débit effectif.
  • Jitter de stockage quand les IRQ tombent sur des cœurs occupés sur le « mauvais » nœud NUMA par rapport au périphérique PCIe.

Règle : si une charge a un état partagé et que vous tenez à la latence, soit vous la maintenez dans un seul domaine de cache, soit vous acceptez le coût et le mesurez. L’espérance n’est pas un plan.

Mémoire et E/S : bande passante, latence, PCIe et réalité du stockage

En production, les CPU échouent rarement parce qu’ils sont « trop lents ». Ils échouent en attendant. En attendant la mémoire. En attendant des locks. En attendant des complétions I/O. Chaque génération Zen modifie ces schémas d’attente.

Bande passante mémoire : l’habilitant silencieux (et la limite silencieuse)

À mesure que le nombre de cœurs augmente, la bande passante par cœur peut chuter si les canaux mémoire ne suivent pas proportionnellement ou si vous sous-populez les DIMM. Le DDR5 de Zen 4 aide, mais il tente aussi les gens à utiliser moins de DIMM « parce que la capacité suffit ». Ensuite ils vous appellent lorsque les tempêtes de compaction et les pauses GC s’aggravent.

Latence mémoire : la taxe que vous payez sur les misses

La latence est façonnée par la vitesse mémoire, les timings, le comportement du contrôleur et la distance du cœur à la mémoire attachée au NUMA node pertinent. Les changements de cache de Zen 3 réduisent la fréquence à laquelle vous payez cette taxe pour certains motifs. Zen 4 peut encore être puni par une mauvaise localité — simplement plus rapidement.

PCIe : quand « plus de lanes » n’est pas « plus de performance »

PCIe 4 vers PCIe 5 double la bande passante théorique, et vous n’obtiendrez absolument pas 2× dans le monde réel à moins que le reste de votre pile suive : firmware NVMe, couche bloc du kernel, traduction IOMMU, routage des IRQ et disponibilité CPU pour les complétions. Les ingénieurs stockage l’apprennent vite : le bus n’est rarement le seul bus.

Changements « ressentis » spécifiques au stockage

  • Plus de potentiel IOPS signifie que vous pouvez atteindre plus tôt les plafonds de surcharge CPU dans le traitement des interruptions NVMe.
  • Potentiel de rebuild/scrub plus rapide est réel, mais seulement si le placement des threads checksum/compression et la bande passante mémoire ne se battent pas avec vous.
  • Convergence réseau + stockage (NIC rapides + SSD rapides) vous pousse dans le territoire « alignement IRQ et NUMA » que vous le vouliez ou non.

Blague #2 : PCIe 5 c’est super — maintenant vous pouvez déplacer les données deux fois plus vite vers l’endroit où votre application attend un mutex.

Virtualisation et ordonnanceurs : la section « pourquoi cette VM a ralenti ? »

L’évolution de la plateforme Zen change l’histoire de la virtualisation de deux manières : la topologie et les mitigations. Les hyperviseurs et les kernels sont meilleurs qu’avant, mais ils font encore des choses stupides quand vous ne leur dites pas ce que « proche » signifie.

Placement de VM et vNUMA : rapprocher le mensonge de la vérité

Si une VM pense avoir un accès mémoire uniforme alors que l’hôte a une topologie multi-NUMA, vous demandez essentiellement à l’invité de prendre de mauvaises décisions d’ordonnancement à grande vitesse. Le pinning et le vNUMA ne sont pas des « micro-optimisations ». Ce sont comment vous empêchez le trafic mémoire inter-nœuds de vous manger le déjeuner.

Mitigations et microcode : les comparaisons de performance ont besoin de contexte

Les mitigations du kernel peuvent changer entre versions d’OS, et les mises à jour de microcode peuvent changer le comportement. Quand quelqu’un dit « Zen 4 n’est que 10 % plus rapide que Zen 3 pour notre charge », votre première question doit être : « Qu’est-ce qui a changé dans le kernel et le firmware, et mesurons-nous la même chose ? »

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

Voici la partie que vous pouvez copier dans vos runbooks. Chaque tâche inclut : une commande, ce que la sortie signifie, et une décision à prendre. Celles-ci sont orientées Linux parce que c’est là que vivent la plupart des serveurs Zen.

Task 1: Identify the CPU generation and stepping

cr0x@server:~$ lscpu | egrep 'Model name|CPU\(s\)|Socket|Thread|NUMA node\(s\)'
Model name:                           AMD EPYC 7B13 64-Core Processor
CPU(s):                               128
Socket(s):                            2
Thread(s) per core:                   2
NUMA node(s):                         8

Signification : Vous voyez la ligne modèle (aide à mapper à la génération Zen) et le nombre de nœuds NUMA (indice majeur sur la topologie).

Décision : Si les nœuds NUMA sont nombreux, planifiez du travail de placement/pinning avant de blâmer l’application.

Task 2: Confirm NUMA topology and CPU-to-node mapping

cr0x@server:~$ numactl --hardware
available: 8 nodes (0-7)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 64412 MB
node 0 free: 51230 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 64500 MB
node 1 free: 52110 MB
...

Signification : Quels cœurs appartiennent à quel nœud NUMA, et mémoire disponible par nœud.

Décision : Pour les services sensibles à la latence, épinglez CPU et mémoire sur un nœud qui a un accès local au NIC/NVMe.

Task 3: Check memory speed and populated channels (quick signal)

cr0x@server:~$ sudo dmidecode -t memory | egrep 'Locator:|Speed:|Configured Memory Speed:|Size:'
Locator: P0_DIMM_A1
Size: 32 GB
Speed: 4800 MT/s
Configured Memory Speed: 4800 MT/s
Locator: P0_DIMM_B1
Size: 32 GB
Speed: 4800 MT/s
Configured Memory Speed: 4800 MT/s

Signification : Si vous tournez réellement aux vitesses attendues et si des DIMM sont présents.

Décision : Si la vitesse configurée est inférieure à l’attendu, corrigez les réglages BIOS ou la population DIMM avant de tuner le logiciel.

Task 4: See if you’re CPU-bound or stuck in I/O wait

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server)  01/10/2026  _x86_64_  (128 CPU)

12:10:01 AM  CPU   %usr  %nice  %sys  %iowait  %irq  %soft  %steal  %idle
12:10:02 AM  all  62.11   0.00  8.40    0.25   0.10   1.20    0.00  27.94
12:10:02 AM    0  95.00   0.00  3.00    0.00   0.00   0.00    0.00   2.00
...

Signification : Un %usr élevé implique du travail CPU ; un %iowait élevé implique que le CPU attend des E/S.

Décision : Si iowait est élevé, arrêtez le « tuning CPU » et inspectez le stockage/réseau. Si un CPU est saturé, suspectez l’affinité IRQ ou un thread chaud unique.

Task 5: Spot run-queue pressure (scheduler saturation)

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
12  0      0 5210432  91232 1832448    0    0    12   144 9800 21000 71  9 20  0  0
18  0      0 5209120  91232 1832600    0    0     0   512 9950 24000 76 10 14  0  0

Signification : r est le nombre de tâches prêtes. Quand il est constamment au-dessus des cœurs disponibles (ou d’un groupe de cœurs que vous surveillez), vous êtes sursouscrit.

Décision : Si la file d’attente est élevée et la latence mauvaise, réduisez la consolidation ou épinglez les charges critiques loin des voisins bruyants.

Task 6: Check frequency behavior and throttling

cr0x@server:~$ lscpu | egrep 'CPU max MHz|CPU MHz'
CPU MHz:                               2890.123
CPU max MHz:                           3650.0000

Signification : Fréquence actuelle vs max.

Décision : Si CPU MHz est bien en dessous de l’attendu sous charge, vérifiez les caps d’alimentation et le thermal throttling dans le BIOS/BMC ; ne perdez pas de temps à « optimiser le code » d’abord.

Task 7: Verify cpufreq governor policy

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

Signification : Le governor affecte le ramping de fréquence et le comportement en régime permanent.

Décision : Pour les services à faible latence, préférez performance (ou des profils tuned) sauf si les contraintes d’énergie sont explicites et mesurées.

Task 8: Inspect kernel NUMA balancing behavior

cr0x@server:~$ cat /proc/sys/kernel/numa_balancing
1

Signification : Le NUMA balancing automatique peut migrer des pages/mémoire pour la localité, causant parfois du jitter de latence.

Décision : Si vous observez des pics de latence périodiques alignés sur des migrations, envisagez de le désactiver pour les workloads épinglés, mais testez — ne faites pas de cargo-cult.

Task 9: Check actual memory locality of a process

cr0x@server:~$ pidof myservice
24819
cr0x@server:~$ numastat -p 24819
Per-node process memory usage (in MBs) for PID 24819 (myservice)
Node 0   Node 1   Node 2   Node 3   Node 4   Node 5   Node 6   Node 7   Total
-----    -----    -----    -----    -----    -----    -----    -----    -----
Anon     812.3     19.5      3.1      0.2      0.1      0.0      0.0      0.0   835.2
File      42.0      1.0      0.0      0.0      0.0      0.0      0.0      0.0    43.0

Signification : La majeure partie de la mémoire est sur le nœud 0, avec de petites allocations distantes ailleurs.

Décision : Si la mémoire est dispersée sur plusieurs nœuds, épinglez avec numactl ou systemd CPUAffinity/NUMAPolicy pour une latence prévisible.

Task 10: Inspect PCIe device locality (which NUMA node owns the device)

cr0x@server:~$ lspci -nn | egrep 'Non-Volatile|Ethernet'
41:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]
c1:00.0 Ethernet controller [0200]: Mellanox Technologies MT28908 Family [ConnectX-6] [15b3:101b]
cr0x@server:~$ cat /sys/bus/pci/devices/0000:41:00.0/numa_node
2
cr0x@server:~$ cat /sys/bus/pci/devices/0000:c1:00.0/numa_node
6

Signification : Le NVMe est le plus proche du nœud NUMA 2 ; le NIC du nœud 6.

Décision : Placez les threads de stockage près du nœud 2, les threads réseau près du nœud 6, ou acceptez la pénalité cross-fabric et mesurez-la.

Task 11: Check IRQ distribution (common Zen “why is one core melting?” issue)

cr0x@server:~$ grep -E 'nvme|mlx|eth' /proc/interrupts | head
  180:  9812234          0          0          0   PCI-MSI 524288-edge      nvme0q0
  181:        0          0          0          0   PCI-MSI 524289-edge      nvme0q1
  190:  5021132          0          0          0   PCI-MSI 532480-edge      mlx5_comp0

Signification : Que toutes les interruptions tombent sur CPU0 (première colonne) est un mauvais signe sauf si vous l’avez délibérément configuré ainsi.

Décision : Si les interruptions sont concentrées, activez et réglez irqbalance ou épinglez les IRQ sur des CPU locaux au nœud NUMA du périphérique.

Task 12: Confirm NVMe queue and latency behavior

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

Device            r/s     w/s   rMB/s   wMB/s  rrqm/s  wrqm/s %rrqm %wrqm r_await w_await aqu-sz  %util
nvme0n1        2200.0  1800.0   350.0   280.0     0.0     0.0  0.00  0.00   0.40    0.55   2.10  78.00

Signification : await est la latence ; aqu-sz indique la profondeur de file ; %util indique la saturation.

Décision : Si %util est proche de 100 et que await augmente, le stockage est saturé. Si await est bas mais l’appli est lente, suspectez CPU/locks/réseau.

Task 13: See if you’re memory-bandwidth bound (quick and dirty)

cr0x@server:~$ perf stat -a -e cycles,instructions,cache-misses,LLC-load-misses,task-clock -- sleep 5
 Performance counter stats for 'system wide':

   98,234,112,991      cycles
   73,120,443,210      instructions              #    0.74  insn per cycle
    1,223,110,992      cache-misses
      401,223,114      LLC-load-misses
       5,002.12 msec   task-clock

       5.000891981 seconds time elapsed

Signification : Un IPC bas plus beaucoup de LLC misses indique souvent des stalls mémoire (pas toujours, mais bon indice).

Décision : Si les stalls mémoire dominent, priorisez la localité de cache, réduisez l’accès mémoire distant, et vérifiez la population/vitesse des DIMM avant de chasser des flags du compilateur.

Task 14: Check CPU migrations (latency jitter hint)

cr0x@server:~$ perf stat -p 24819 -e context-switches,cpu-migrations -a -- sleep 10
 Performance counter stats for 'system wide':

       210,554      context-switches
        12,321      cpu-migrations

      10.004112343 seconds time elapsed

Signification : Des migrations CPU élevées peuvent signifier que vos threads rebondissent entre cœurs/nœuds NUMA.

Décision : Si le p99 est mauvais et les migrations élevées, envisagez l’affinité CPU, les cgroups cpusets, ou le tuning de l’ordonnanceur. Ne vous contentez pas d’« ajouter des replicas ».

Task 15: Validate hugepages status (VM and DB workloads care)

cr0x@server:~$ grep -E 'HugePages|Hugepagesize' /proc/meminfo
HugePages_Total:     8192
HugePages_Free:      7901
Hugepagesize:        2048 kB

Signification : Hugepages configurées et disponibles.

Décision : Si vous dépendez des hugepages et qu’elles sont épuisées, vous aurez des pics de latence et de la pression TLB ; ajustez l’allocation ou corrigez les fuites/la fragmentation.

Task 16: Check KVM and nested virtualization flags (cloud/VM hosts)

cr0x@server:~$ lsmod | grep kvm
kvm_amd               155648  0
kvm                  1064960  1 kvm_amd
cr0x@server:~$ cat /sys/module/kvm_amd/parameters/nested
0

Signification : Si la virtualisation imbriquée est activée sur l’hôte.

Décision : Activez-la uniquement si nécessaire. Le nested peut compliquer performances et debugging ; le « juste au cas où » est la source de surcoût mystérieux.

Plan de diagnostic rapide : trouver le goulot vite

Voici la séquence de triage que j’utilise quand quelqu’un dit : « On est passé de Zen X à Zen Y et ce n’est pas plus rapide » ou « c’est plus rapide mais la latence s’est dégradée ». N’improvisez pas. Exécutez le plan.

Première étape : confirmer la réalité de la plateforme (5 minutes)

  1. CPU + nombre NUMA (lscpu) : êtes-vous sur le matériel attendu ? Les réglages BIOS ont-ils changé l’exposition NUMA ?
  2. Vitesse et population mémoire (dmidecode) : tournez-vous aux MT/s attendus ? Les canaux sont-ils sous-populés ?
  3. Gouverneur et fréquence (scaling_governor, lscpu) : êtes-vous coincé dans une politique d’économie d’énergie ?

Deuxième étape : classer le goulot (10 minutes)

  1. CPU vs iowait (mpstat) : user/system élevé vs iowait élevé.
  2. Pression sur la file d’exécution (vmstat) : êtes-vous sursouscrit ?
  3. Indice stalls mémoire (perf stat) : IPC bas + beaucoup de LLC misses suggère mémoire-bound.

Troisième étape : alignement de la topologie (15–30 minutes)

  1. Localité mémoire du process (numastat -p) : le process est-il majoritairement local ?
  2. Nœud NUMA du périphérique (/sys/bus/pci/.../numa_node) : NVMe/NIC sont-ils proches des cœurs qui font le travail ?
  3. Distribution des interruptions (/proc/interrupts) : les IRQ font fondre un cœur ?

Condition d’arrêt : une fois que vous trouvez une classe de goulot (CPU, mémoire, E/S, topologie), arrêtez de collecter des métriques aléatoires. Faites un changement, mesurez, puis avancez.

Trois mini-récits d’entreprise (anonymisés, réalistes et un peu douloureux)

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

L’entreprise a migré une flotte de serveurs API de Zen 2 à Zen 4. Les tests de performance étaient excellents : débit en hausse, latence moyenne en baisse. Ils ont déployé progressivement. Dans la semaine, l’incident : des pics de latence p99 toutes les quelques minutes, seulement sur la nouvelle flotte, seulement sous trafic mixte.

L’équipe on-call a fait ce que tout le monde fait sous pression : elle a regardé l’utilisation CPU. C’était normal. Ils ont regardé le GC. Normal. Ils ont regardé le load balancer. Lui aussi semblait normal, probablement pour faire bonne mesure.

La mauvaise hypothèse était subtile : « NUMA est géré par le kernel maintenant. » Sur les anciens hôtes, le NIC et les threads les plus occupés du service se trouvaient sur le même nœud NUMA à cause du câblage du châssis. Sur les nouveaux hôtes, le NIC était sur un nœud différent. Le service était aussi configuré avec un CPU set qui épinglait ses workers sur les « premiers » cœurs — pratique, stable, et maintenant très loin du NIC.

Chaque paquet faisait un aller-retour supplémentaire sur le fabric. Sous faible trafic, ça passait. Sous charge, la latence additionnelle et les misses cache cross-node se sont transformées en une falaise périodique, parce que le nœud occupé s’engorgeait et que le kernel commençait à migrer des choses pour compenser.

La correction fut ennuyeuse : aligner l’affinité CPU des workers avec le nœud NUMA du NIC, et s’assurer que la politique mémoire matchait. Les pics ont disparu immédiatement. Personne n’a voulu admettre que c’était « juste » la topologie, mais les graphes se moquaient de l’ego.

Mini-récit 2 : L’optimisation qui s’est retournée contre eux

Une équipe stockage a mis à niveau des serveurs metadata de Zen 3 à Zen 4. Voyant de la marge, un ingénieur a augmenté la concurrence : plus de threads workers, files plus profondes, tailles de lots plus grandes. L’idée était « utiliser tous ces cœurs ». Et ça a marché — jusqu’à ce que ça ne marche plus.

Le premier symptôme n’était pas la performance ; c’était la variabilité. La latence est devenue plus piquante, pas forcément plus lente en moyenne. Les jobs de maintenance nocturnes ont commencé à chevaucher les pics diurnes d’une façon inédite. Rien n’était « saturé » dans les métriques évidentes.

Le retour de flamme était classique : la nouvelle concurrence a poussé la charge d’un régime CPU-bound vers un régime lié à la bande passante mémoire. Zen 4 a déplacé le plafond, mais le motif d’accès de la charge — beaucoup de pointer chasing, beaucoup de misses de cache — signifiait que le CPU attendait la plupart du temps. Les threads supplémentaires ont augmenté la contention et le churn de cache, et le système a passé plus de temps à coordonner qu’à faire du travail utile.

Ils ont rollbacké l’augmentation de concurrence et re-testé. Le débit a un peu diminué, mais le p99 s’est stabilisé et le chevauchement des maintenances a cessé de provoquer des douleurs visibles clients. Puis ils ont fait la vraie correction : un sharding plus réfléchi des métadonnées chaudes, plus l’épinglage des threads les plus bavards dans un domaine de localité plus restreint.

La leçon : des comptes de cœurs plus élevés ne signifient pas que vous devez augmenter la concurrence aveuglément. Il est facile de créer un goulot plus rapide et d’appeler ça une amélioration.

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

Une équipe plateforme avait une habitude que d’autres équipes se moquaient : chaque nouvelle génération matérielle passait par la même checklist d’acceptation. Version BIOS, niveau microcode, version kernel, politique governor, paramètres IOMMU, et un petit ensemble de « smoke benchmarks » reproductibles. Ce n’était pas glamour. Ça n’attirait pas les applaudissements.

Pendant un déploiement Zen 4, ils ont remarqué une anomalie petite mais cohérente : un lot de nœuds avait une fréquence soutenue plus basse sous charge et un p99 pire dans leurs tests smoke. Pas catastrophique. Juste « étrange ». La différence corrélait avec un profil BIOS légèrement différent expédié par le fournisseur sur ce lot.

Ils ont mis en pause le rollout pour ces nœuds uniquement, corrigé le profil BIOS, et repris. Deux semaines plus tard, une autre équipe a découvert que ses propres nœuds se bridaient sous des jobs batch — parce qu’ils n’avaient pas standardisé le firmware et avaient supposé que les valeurs par défaut suffisaient.

L’équipe plateforme n’a pas semblé héroïque sur le moment. Ils n’ont pas non plus eu d’incident. Leur pratique était ennuyeuse, et ennuyeuse est le but.

Erreurs courantes : symptômes → cause racine → correction

Cette section est à coller dans un ticket d’incident. Symptômes spécifiques, causes probables, et corrections qui changent réellement les résultats.

1) Symptom: p99 latency worse after upgrade, average latency better

Cause racine : mismatch de topologie (threads éloignés du NIC/NVMe), migrations CPU accrues, ou effets secondaires du NUMA balancing sur un système à plus forte densité de cœurs.

Correction : Vérifiez le nœud NUMA du périphérique et épinglez les threads de service en conséquence ; vérifiez la localité mémoire avec numastat ; réduisez les migrations avec affinity/cpuset ; envisagez de désactiver le NUMA balancing pour les services épinglés.

2) Symptom: NVMe benchmarks improved, but application I/O didn’t

Cause racine : l’appli est CPU-bound dans le traitement syscall/interrupt/completion ; IRQ concentrées sur un seul cœur ; overhead IOMMU/remapping d’interruptions ; paramètres de queues suboptimaux.

Correction : Inspectez /proc/interrupts ; distribuez les IRQ ; assurez-vous que les queues sont configurées ; mesurez l’usage CPU en softirq ; épinglez les threads I/O localement au périphérique.

3) Symptom: One core pegged at 100% sys while others idle

Cause racine : affinité IRQ épinglée sur un seul CPU (ou irqbalance désactivé), ou un thread kernel chaud unique.

Correction : Réactivez irqbalance ou définissez manuellement l’affinité IRQ ; vérifiez avec /proc/interrupts et recontrôlez sous charge.

4) Symptom: Throughput scales until N threads, then flatlines

Cause racine : saturation de la bande passante mémoire, contention de locks, ou trafic cross-NUMA dominant.

Correction : Utilisez perf stat pour chercher des stalls ; réduisez l’accès cross-node ; shardez les locks ; considérez des structures de données cache-friendly ; n’ajoutez pas juste des threads.

5) Symptom: “New CPUs are slower” on a VM host

Cause racine : oversubscription vCPU, vNUMA mal configuré, mitigations activées différemment, ou politique d’alimentation de l’hôte changée.

Correction : Vérifiez la file d’exécution et le steal time ; alignez le vNUMA avec la topologie physique ; assurez une politique kernel/microcode cohérente ; définissez le governor.

6) Symptom: Storage rebuild/scrub is slower on newer nodes

Cause racine : threads checksum/compression planifiés loin des disques ; contention de bande passante mémoire avec services co-localisés ; canaux mémoire sous-populés.

Correction : Placez les workers stockage près du nœud NUMA NVMe ; réservez des cœurs ; peuplez correctement les canaux mémoire ; mesurez la bande passante et les stalls CPU.

7) Symptom: Random latency spikes every few minutes

Cause racine : travaux kernel de fond (migrations de pages NUMA, kswapd), oscillations thermique/power limit, ou jobs périodiques de maintenance qui se mettent à se chevaucher à cause d’enveloppes de performance différentes.

Correction : corrélez les pics avec les migrations (perf migrations, changements numastat), vérifiez les fréquences et le throttling, replanifiez les maintenances, et isolez les charges.

Listes de contrôle / plan pas-à-pas

Checklist de planification de montée de version (avant d’acheter ou de réallouer une flotte)

  1. Classifiez les workloads : tier latence vs tier débit. Placez-les sur les bons SKU (les pièces à cœurs denses ne sont pas magiques pour la latence mono-thread).
  2. Inventoriez les goulots aujourd’hui : CPU, bande passante mémoire, latence mémoire, E/S, ou contention de locks. Utilisez d’abord le playbook « Fast diagnosis ».
  3. Décidez ce que « mieux » signifie : p99, débit à p99 fixé, watts par requête, temps de rebuild, ratio de consolidation. Choisissez deux, pas sept.
  4. Planifiez la gouvernance firmware : version BIOS/AGESA, politique microcode, version kernel. Traitez-les comme des dépendances figées avec déploiement contrôlé.
  5. Concevez une politique NUMA : allez-vous épingler ? Utiliser des cpusets ? Laisser l’ordonnanceur ? Décidez délibérément.
  6. Vérifiez les règles de population mémoire : canaux remplis pour la bande passante, pas seulement pour la capacité.
  7. Cartographiez la localité des périphériques : où sont connectés NICs et NVMe ? Assurez-vous que le layout du châssis correspond à votre modèle de placement de charge.

Checklist d’acceptation (premier rack de nouvelle génération)

  1. Exécutez lscpu et enregistrez le modèle CPU, les nœuds NUMA, le max MHz.
  2. Exécutez dmidecode et confirmez que la vitesse mémoire configurée correspond à l’attendu.
  3. Confirmez le governor : performance (ou votre politique choisie).
  4. Vérifiez la distribution des IRQ sous charge synthétique ; corrigez si concentrée.
  5. Exécutez un canary de service niveau applicatif et comparez p50/p99, pas seulement le débit.
  6. Exécutez des tests smoke stockage/réseau et assurez-vous que le nœud NUMA du périphérique correspond à la stratégie de placement des threads.

Checklist opérationnelle (continu)

  1. Standardisez les profils BIOS et auditez les dérives.
  2. Suivez les changements de kernel et microcode comme partie des baselines de performance.
  3. Alertez sur anomalies de fréquence (horloges soutenues sous l’attendu en charge).
  4. Alertez sur hotspots IRQ (un seul CPU recevant une proportion disproportionnée d’interruptions).
  5. Revuez la pression de consolidation : files d’attente, steal time, effets de voisins bruyants.

FAQ

1) Zen 3 est-elle la « grande » génération pour les applis sensibles à la latence ?

Souvent, oui — parce que le changement de domaine de cache (L3 unifié par CCD) réduit certaines pénalités cross-core. Mais la vraie réponse dépend de la quantité de partage de données entre threads de votre workload et de sa sensibilité aux misses de cache.

2) Pourquoi mon p99 s’est-il détérioré après le passage à un CPU plus récent ?

Parce que vous avez changé la topologie et le comportement, pas seulement la vitesse. Causes courantes : les threads s’exécutent maintenant loin du NIC/NVMe ; les migrations CPU ont augmenté ; le NUMA balancing a commencé à déplacer des pages ; ou vous avez atteint un nouveau goulot (bande passante mémoire, gestion des IRQ).

3) Dois-je épingler les processus sur les systèmes Zen modernes ?

Si vous tenez à une latence prévisible, oui, au moins pour les composants critiques. Si vous exécutez des jobs batch/de débit, vous pouvez souvent compter sur l’ordonnanceur. Mélanger les deux sans pinning est la recette pour « rapide en moyenne, catastrophique quand ça compte ».

4) Le DDR5 est-il toujours un gain ?

Pas automatiquement. Il élève les plafonds de bande passante, mais la latence et la configuration comptent. Sous-populer les canaux peut effacer les gains. Mesurez avec votre workload, pas avec l’espoir.

5) Comment savoir si je suis limité par la mémoire après une montée de version Zen ?

Recherchez un IPC bas avec beaucoup de LLC misses (perf stat), et un scaling qui cesse de s’améliorer quand vous ajoutez des threads. Puis validez que la mémoire est locale (numastat) et que canaux/vitesses sont correctement configurés.

6) Quel est le problème « caché » le plus courant sur les nœuds de stockage avec les nouvelles générations Zen ?

La localité des interruptions et le placement CPU par rapport au NVMe. Le matériel est assez rapide pour que vos erreurs de routage IRQ deviennent le goulot.

7) Dois-je désactiver le NUMA balancing ?

Pour des services épinglés sensibles à la latence, cela peut réduire le jitter. Pour des systèmes multi-tenant généralistes, cela peut améliorer l’efficacité globale. La bonne réponse : testez sur votre workload exact et comparez le p99, pas seulement la moyenne.

8) Les générations Zen changent-elles le comportement de ZFS ?

ZFS dépend du CPU pour checksums/compression, de la bande passante mémoire pour l’ARC et des workloads riches en métadonnées, et des E/S pour la latence des vdev. Les Zen plus récents peuvent accélérer les parties CPU, mais ils rendent aussi la localité IRQ et la configuration mémoire plus importantes.

9) Quelle est une façon pratique de comparer équitablement des générations Zen ?

Maintenez constants : version du kernel, politique de mitigations, réglages BIOS, population/vitesses mémoire, placement stockage/NIC, et version du workload. Puis comparez à p99 fixe ou à débit fixe — ne laissez pas la métrique dériver.

Conclusion : prochaines étapes concrètes

L’évolution de Zen est réelle, et vous la ressentez — mais pas toujours là où la fiche technique le suggère. Zen 3 a rendu beaucoup de problèmes de latence moins dramatiques en changeant les domaines de cache. Zen 4 a déplacé le plafond de la plateforme avec DDR5 et PCIe 5, ce qui signifie que vos anciennes habitudes « suffisantes » en I/O et topologie peuvent désormais être votre goulot.

Prochaines étapes qui rapportent rapidement :

  1. Exécutez le playbook Fast diagnosis sur un nœud représentatif par génération. Ne devinez pas.
  2. Cartographiez la localité de vos périphériques (NIC/NVMe → nœud NUMA) et alignez les threads critiques en conséquence.
  3. Auditez la configuration mémoire : canaux peuplés et vitesses configurées, pas seulement le total GB.
  4. Vérifiez la distribution des IRQ sous charge et corrigez les hotspots avant qu’ils ne deviennent « saturation CPU mystérieuse ».
  5. Standardisez les baselines firmware et kernel pour la flotte et traitez la dérive comme un risque de production.

Si vous faites ces cinq choses, les montées de version Zen cessent d’être un saut dans l’inconnu et redeviennent ce qu’elles devraient être : un changement d’ingénierie que vous pouvez raisonner, mesurer et déployer sans surprises.

← Précédent
Sécurité de zfs destroy : Les vérifications qui empêchent « Oups, mauvais dataset »
Suivant →
Debian 13 « Unable to locate package » : pièges de dépôts, d’architecture et de sources.list (et correctifs)

Laisser un commentaire