CPU : ce que fait le processeur, et ce qui le sature

Le CPU (Central Processing Unit, ou processeur) est le circuit qui lit, décode et exécute les instructions d'un ordinateur, à raison de plusieurs milliards de cycles par seconde. Sur un serveur, c'est lui qui chiffre le TLS, absorbe les interruptions de la carte réseau et fixe, en pratique, le nombre de requêtes par seconde que la machine encaisse avant de plier.

Ce qu’un CPU fait réellement à chaque cycle

Le processeur répète une boucle très simple : il va chercher une instruction en mémoire, la décode, l'exécute, range le résultat. Un cœur cadencé à 3 GHz déclenche 3 milliards de cycles par seconde, et grâce au pipeline et à l'exécution superscalaire il achève souvent plus d'une instruction par cycle. Cette valeur porte un nom, l'IPC (instructions par cycle), et elle explique pourquoi comparer deux processeurs sur leur seule fréquence ne veut rien dire.

La fréquence plafonne d'ailleurs depuis le milieu des années 2000, autour de 3 à 5 GHz, parce que la consommation et la chaleur montent plus vite que le gain de performance. Les fondeurs ont donc empilé des cœurs plutôt que des hertz. Un processeur de 2024 à 3 GHz dépasse largement un Pentium 4 à 3,8 GHz de 2004, sur à peu près toutes les charges.

Le vrai goulot d'étranglement est ailleurs : la mémoire. Un accès au cache L1 coûte environ quatre cycles, un accès à la RAM entre deux et trois cents. D'où la hiérarchie de caches présente sur tous les processeurs modernes. Un programme qui saute au hasard dans un gros tableau passe l'essentiel de son temps à attendre la RAM, et votre moniteur affiche pourtant 100 % de CPU : le cœur est occupé, il ne produit rien.

  • Cache L1 : 32 à 64 Ko par cœur, environ 4 cycles de latence, séparé en données et instructions
  • Cache L2 : 512 Ko à 2 Mo par cœur, de l'ordre de 12 à 20 cycles
  • Cache L3 : quelques Mo à plus de 100 Mo, partagé entre les cœurs, 40 à 60 cycles
  • RAM : 200 à 300 cycles, soit grossièrement 60 à 100 nanosecondes

Cœur, thread, vCPU, socket : quatre choses différentes

La confusion la plus coûteuse en production porte sur ce qu'on achète quand on achète « 4 CPU ». Un cœur physique est une unité d'exécution complète. Un thread SMT (Hyper-Threading chez Intel) est une seconde file d'instructions qui partage les mêmes unités de calcul : le gain typique se situe autour de 15 à 30 % de débit supplémentaire, pas 100 %. Sur la plupart des instances cloud x86, le vCPU facturé correspond à un thread, pas à un cœur.

Il existe des exceptions utiles à connaître. Les instances ARM Graviton d'AWS n'implémentent pas le SMT : un vCPU y vaut un cœur physique. Un `lscpu` le montre en une ligne, avec le champ « Thread(s) per core » à 1 ou à 2. Vérifiez-le avant de comparer deux offres au prix du vCPU.

Autre glissement de vocabulaire, franco-français celui-là : « unité centrale » désigne dans le langage courant le boîtier de la tour, pas le processeur. Et le CPU n'est pas le GPU : le premier est optimisé pour enchaîner vite des tâches variées et pleines de branchements, le second pour appliquer le même calcul à des milliers de données en parallèle. Un ASIC de minage, lui, ne sait faire qu'une seule chose, mais mille fois mieux qu'eux deux.

TermeCe que c'estCe que montre Linux
SocketLe boîtier physique enfiché sur la carte mèreChamp physical id dans /proc/cpuinfo
Cœur physiqueUnité d'exécution complète avec ses caches L1 et L2Champ core id, et Core(s) per socket dans lscpu
Thread (SMT)Une seconde file d'instructions sur le même cœurDeux lignes processor pour un même core id
vCPUL'unité facturée par l'hébergeur, en général un threadIndiscernable d'un cœur, sauf par le steal time

Le CPU sur le chemin des paquets

Chaque paquet qui arrive coûte du processeur. La carte réseau lève une interruption matérielle, le noyau bascule en interruption logicielle (softirq NET_RX), puis remonte la pile jusqu'à la socket. Le volume est vite considérable : à 1 Gbit/s avec des trames Ethernet de taille minimale, le lien porte 1 488 095 paquets par seconde. Le calcul tient en une ligne : 64 octets de trame plus 8 de préambule et 12 d'intervalle inter-trames font 84 octets, soit 672 bits, et 1 000 000 000 divisé par 672 donne ce chiffre.

Un seul cœur ne suit pas ce rythme. C'est le rôle du RSS (Receive Side Scaling) : la carte répartit les flux sur plusieurs files matérielles, chacune associée à un cœur via l'affinité des IRQ. Quand ce réglage manque, vous voyez `ksoftirqd/0` collé à 100 % pendant que les autres cœurs dorment, avec des pertes de paquets à la clé. `ethtool -l eth0` donne le nombre de files disponibles, `cat /proc/interrupts` montre leur répartition réelle.

Le chiffrement est l'autre gros poste. Depuis 2010 et l'architecture Westmere, les processeurs x86 embarquent les instructions AES-NI ; côté ARM, ce sont les extensions cryptographiques d'ARMv8. La différence se mesure en une commande. Comparez `openssl speed -evp aes-128-gcm` avec la même commande privée de l'accélération matérielle : `OPENSSL_ia32cap="~0x200000200000000" openssl speed -evp aes-128-gcm`. L'écart se compte en facteur, pas en pourcents. Le flag `aes` dans /proc/cpuinfo vous dit si la machine en dispose.

Le coût du handshake TLS, lui, dépend du type de certificat. Lancez `openssl speed rsa2048 ecdsap256` : la signature ECDSA P-256, celle que le serveur effectue à chaque poignée de main, sort environ un ordre de grandeur au-dessus de RSA 2048 sur la même machine. Passer un certificat de RSA à ECDSA reste l'un des rares gains de capacité qui ne coûte rien d'autre qu'une réémission.

Dernier point où le processeur et le réseau se rencontrent, et qui piège encore des développeurs : l'ordre des octets. Le réseau est big-endian, x86 est little-endian, d'où les conversions `htons()` et `htonl()`. Oubliez `htons()` sur un numéro de port et votre 80 part sur le fil en 20480. Le service écoute, la connexion n'arrive jamais, et rien dans les logs ne l'explique.

Lire une charge CPU sous Linux sans se tromper de coupable

Le load average affiché par `uptime` ou `top` donne trois moyennes, sur 1, 5 et 15 minutes. Piège classique : sous Linux, il ne compte pas que les tâches prêtes à s'exécuter, il inclut aussi celles bloquées en attente d'entrées-sorties (état D). Un load de 12 sur une machine à 4 cœurs peut donc signaler un disque saturé et un processeur à moitié inactif. Comparez toujours le load au nombre de CPU logiques renvoyé par `nproc`.

Pour savoir où part le temps, la ventilation par état est plus parlante que le total. Dans `top`, la touche 1 déplie les cœurs un par un ; `mpstat -P ALL 1` (paquet sysstat) fait la même chose en continu, et `pidstat 1` descend au processus.

Un cas de terrain fréquent : un serveur nginx en VPS mutualisé qui répond mal sans que rien ne bouge côté applicatif. Regardez %st. Au-delà de quelques pour cent en continu, l'hyperviseur donne vos cycles à un voisin, et aucun réglage de votre côté n'y changera quoi que ce soit. Le correctif est commercial, pas technique : changer d'instance ou d'hébergeur. À l'inverse, un %sy élevé pointe vers le noyau, souvent trop d'appels système ou trop de petits paquets, et un %si élevé désigne directement la pile réseau.

Côté configuration, la directive `worker_processes auto` de nginx aligne le nombre de processus de travail sur le nombre de cœurs détectés. Au-delà, vous ajoutez des changements de contexte sans ajouter de capacité.

Colonne de topSignificationCe qu'un chiffre élevé suggère
%usCode applicatif en espace utilisateurCharge normale, ou boucle de calcul mal optimisée
%syCode du noyau, appels systèmeTrop de syscalls, beaucoup de petits paquets
%waAttente d'entrées-sortiesDisque ou stockage réseau saturé, pas le CPU
%hiInterruptions matériellesCarte réseau ou contrôleur qui interrompt sans relâche
%siInterruptions logiciellesTraitement réseau concentré sur un cœur, RSS mal réparti
%stTemps volé par l'hyperviseurHôte de virtualisation surchargé, voisin bruyant

CPU et sécurité : failles matérielles, minage et attaques asymétriques

Janvier 2018 a fait entrer le processeur dans la surface d'attaque ordinaire avec la divulgation de Spectre (CVE-2017-5753 et CVE-2017-5715) et Meltdown (CVE-2017-5754). Ces failles exploitent l'exécution spéculative, un mécanisme de performance présent depuis des décennies, pour lire de la mémoire qui devrait rester inaccessible. Les parades sont venues du noyau et du microcode : KPTI pour l'isolation des tables de pages, retpoline côté compilateur. Elles ont un coût, surtout sur les charges riches en appels système. L'état de votre machine se lit d'une commande : `grep . /sys/devices/system/cpu/vulnerabilities/*`.

Le SMT a été touché par la suite (L1TF, MDS). OpenBSD a désactivé l'Hyper-Threading par défaut dès juin 2018. Sur un serveur qui exécute du code non fiable, c'est un arbitrage à poser explicitement ; sur une machine qui n'exécute que votre code, la question se pose beaucoup moins.

Le cryptojacking reste la façon la plus banale de voir un CPU détourné. Monero utilise depuis fin 2019 l'algorithme RandomX, conçu pour tourner efficacement sur des processeurs généralistes, ce qui rend le minage rentable sur des serveurs compromis. La signature est reconnaissable : tous les cœurs à 100 % en dehors des pics de trafic, un binaire au nom anodin lancé depuis /tmp ou /dev/shm, et des connexions sortantes vers un pool sur des ports comme 3333, 4444 ou 14444. Une règle de sortie sur le pare-feu coupe court dans la plupart des cas.

Enfin, certaines attaques réseau visent le processeur plutôt que la bande passante. Un SYN flood mobilise le noyau à chaque segment entrant pour une fraction du coût côté attaquant ; `net.ipv4.tcp_syncookies=1`, actif par défaut sur la plupart des distributions, limite les dégâts. Un flood de handshakes TLS relève de la même logique : le client envoie quelques centaines d'octets, le serveur répond par une signature asymétrique. C'est là que le choix du certificat évoqué plus haut cesse d'être une optimisation de confort.

Testez vos connaissances

Quiz rapide Question 1 sur 3

À 1 Gbit/s avec des trames Ethernet de taille minimale, combien de paquets par seconde le lien transporte-t-il ?

Questions fréquentes

Combien de cœurs faut-il pour un serveur web ?

Cela dépend de ce qui consomme le temps. Un site statique ou bien mis en cache tient sur 1 ou 2 cœurs pour des milliers de requêtes par seconde, parce que le travail réel se limite à du réseau et du TLS accéléré par AES-NI. Une application PHP ou Python sans cache d'opcode ni cache applicatif consommera plusieurs cœurs pour quelques dizaines de requêtes par seconde. Mesurez avec `pidstat 1` sous charge réelle avant de dimensionner.

Un load average de 8 est-il grave ?

La réponse dépend du nombre de CPU logiques. Sur une machine à 16 threads, un load de 8 correspond à une machine à moitié occupée. Sur 4 threads, il indique que deux fois plus de tâches attendent que la machine ne peut en traiter. Et comme Linux inclut dans ce chiffre les tâches bloquées en attente d'entrées-sorties, vérifiez %wa dans `top` avant de conclure que le processeur est en cause.

Quelle est la différence entre un CPU et un vCPU ?

Un CPU physique est un composant matériel. Un vCPU est une unité de facturation et d'allocation exposée par un hyperviseur. Sur la plupart des instances x86, un vCPU correspond à un thread SMT, donc à la moitié d'un cœur partagé avec un autre vCPU. Les offres ARM sans SMT, comme Graviton chez AWS, associent un vCPU à un cœur physique entier : à nombre de vCPU égal, la capacité réelle n'est pas la même.

Mon steal time monte à 20 %, que faire ?

Le %st mesure le temps où votre machine virtuelle était prête à travailler mais où l'hyperviseur servait quelqu'un d'autre. Vous ne pouvez rien y faire depuis l'intérieur de la VM : aucun réglage noyau ni aucune optimisation applicative ne récupère ces cycles. Les options réalistes sont de basculer sur une instance à CPU dédié, de changer d'hôte physique en recréant l'instance, ou d'ouvrir un ticket chez l'hébergeur avec des relevés `mpstat` à l'appui.

Faut-il désactiver l’Hyper-Threading ?

Sur un serveur qui héberge du code de tiers non fiables, mutualisé ou multi-locataire, la désactivation limite l'exposition aux attaques par canal auxiliaire de type L1TF et MDS ; OpenBSD le fait par défaut depuis 2018. Le prix à payer est une perte de débit de l'ordre de 15 à 30 % sur les charges parallèles. Sur un serveur dédié à votre seule application, avec un noyau et un microcode à jour, le rapport bénéfice/coût penche généralement vers le maintien du SMT.

À lire aussi

cache · chiffrement · cloud · bande passante

Newsletter

Recevez nos guides IP & réseau

Nouveaux outils, définitions et astuces sécurité, directement par email. Pas de spam, désinscription en un clic.