...

Petites files d'attente TCP : réduire de manière ciblée la latence sur le réseau Linux

La fonctionnalité « TCP Small Queues » limite, pour chaque flux TCP, le nombre d'octets en attente dans la pile d'envoi Linux, ce qui réduit ainsi Latence ainsi que le « bufferbloat », de manière ciblée. Je vais vous montrer comment ce mécanisme fonctionne dans le réseaux sous Linux Stack montre comment définir des limites pertinentes et quelles interactions en découlent avec le pacing, les QDiscs et le contrôle de la congestion.

Points centraux

  • Limite de débit: TSQ limite le nombre d'octets en attente par socket TCP.
  • Moins de « buffer bloat »: Des files d'attente plus courtes réduisent le temps de réponse (RTT).
  • Pression de retour: Les applications s'exécutent plus lentement lorsque la limite est atteinte.
  • Équité: Aucun flux ne monopolise à lui seul l'intégralité des files d'attente.
  • Adaptatif Contrôle : la limite dépend du débit et de la taille du segment.

Comment fonctionne TCP Small Queues

TSQ intervient là où les segments TCP sont QDisc et les pilotes. Lorsque j'écris des données dans un socket, le noyau vérifie, avant chaque mise en file d'attente, les octets déjà alloués pour ce flux. Si le flux atteint la limite, le système marque le socket comme « limité » et interrompt toute nouvelle mise en file d'attente. Ce n’est que lorsque la carte réseau libère de la mémoire tampon que le socket est autorisé à envoyer à nouveau et que je peux réinjecter des données dans la pile. Cette contrainte stricte maintient la Files d'attente est plus court et rend les temps de réponse plus prévisibles.

Pourquoi les longues files d'attente augmentent le temps de réponse

Créer des files d'attente de pilotes et de QDisc de grande taille Bufferbloat, notamment avec TSO/GSO et des volumes de transmission élevés. Un téléchargement volumineux peut saturer les files d’attente de sortie, tandis que les flux interactifs tels que SSH, les appels API ou la VoIP se retrouvent relégués en fin de file. La file d’attente surchargée domine alors la RTT plutôt que le temps de liaison proprement dit. Le contrôle de congestion réagit lentement, car les accusés de réception arrivent en retard, et prend des décisions moins judicieuses concernant la valeur cwnd. Le TSQ limite le nombre d'octets mis en mémoire tampon par flux, afin que les petits paquets urgents puissent être transmis rapidement sur la ligne.

Coup d'œil sous le capot : ce que compte le noyau

En réalité, le noyau ne compte pas les „ paquets “, mais les octets, ou plus précisément les octets de mémoire déjà placés en file d'attente par le socket. Ce qui importe, c'est ce que la pile contient en termes de structures skbuff, y compris truesize a alloué et qui n'a pas encore été traité par le NIC. TSQ y associe un Accélération/Décélération- Chemin : lorsqu’un socket atteint le crédit, la pile active un indicateur de limitation et ne s’appelle à nouveau qu’après l’achèvement des transmissions (NAPI/IRQ) write_space() afin que l'application puisse renvoyer les données. Ce retour d'information est plus rapide que les signaux de contrôle de congestion basés uniquement sur les pertes et intervient avant le QDisc. Avec TSO/GSO, le mécanisme reste efficace, car la limite est fixée à avant en fonction du budget d'octets alloué à la segmentation : les super-trames volumineuses ne sont admises dans le QDisc que s'il reste suffisamment de crédit disponible, ce qui permet de limiter les rafales.

Limites dynamiques et rythme

Je tire profit de TSQ, car la limite ne reste pas figée, mais s'adapte à Taux et tient compte de la taille des segments. L’objectif est d’atteindre environ une milliseconde de données sur le chemin de transmission par flux, que le débit soit de 100 Mbit, 1 Gbit ou 10 Gbit. Sur une ligne rapide, le crédit d’octets autorisé augmente ; sur une ligne lente, il diminue. Associé au TCP-Pacing, cela permet de limiter la taille des rafales et d’accélérer le retour des accusés de réception. J’obtiens ainsi une réduction sensible Pics de latence, sans réduire inutilement le débit.

Interaction par socket et par application

Le TSQ ne fonctionne correctement que si l'application perçoit également la contre-pression. Je tiens donc compte de paramètres tels que SO_SNDBUF, TCP_NOTSENT_LOWAT et l'autocorking. Une fenêtre de tampon d'envoi trop grande peut, à court terme, pousser un grand nombre d'octets dans la pile ; le TSQ ralentit certes, mais l'application ne s'en rend compte que lorsque send() se bloque ou renvoie EAGAIN. Avec TCP_NOTSENT_LOWAT je gère la partie „ non envoyée “ dans l'espace utilisateur et complète ainsi le TSQ côté noyau. L'autocorking (ou explicitement TCP_CORK/MSG_MORE) permet de regrouper les petites écritures sans générer de pics de latence. Limites de rythme par socket (par exemple via SO_MAX_PACING_RATE) s'accordent avec TSQ : le débit assure la régularisation temporelle, tandis que la limite d'octets assure la limitation spatiale. Important : TCP_NODELAY Cela désactive Nagle et peut améliorer l'interactivité, mais sans TSQ, le risque de « burst » augmente ; avec TSQ, je maîtrise les deux aspects.

Guide pratique : valeurs TSQ pertinentes

Je définis le cadre général avec net.ipv4.tcp_limit_output_bytes (Sysctl). Les valeurs par défaut habituelles se situent entre 128 et 262 Ko par flux. Pour de nombreuses charges de travail Web et API, j’opte pour des valeurs plus faibles afin que les réponses interactives restent rapides. Pour les sauvegardes ou la réplication, j’augmente modérément cette limite, tant que le temps de transit (RTT) reste stable. Si vous souhaitez approfondir le sujet des files d’attente, vous trouverez des notions de base sur Files d'attente de paquets sur le serveur, qui facilitent la classification.

Scénario Taux de liaison Valeur par défaut de tcp_limit_output_bytes Objectif
API/HTTP très interactif 100 Mbit – 1 Gbit 64 à 128 Ko faible RTT, petits crampons
Charge mixte : Web + téléchargements 1 à 10 Gbit 128 à 256 Ko Solde de Débit et la latence
Réplication/Sauvegardes 1 à 10 Gbit 256 à 512 Ko débit massique constant, acceptable Latence
WAN à RTT élevé 10 à 100 Mbit 96 à 192 Ko des rafales plus courtes, plus équitables Queues de billard

Interaction entre QDisc et le contrôle de congestion

Le TSQ fonctionne à l'entrée de la QDisc, tandis que des algorithmes tels que fq_codel gèrent la congestion sur la ligne. Ensemble, ils réduisent les files d'attente et garantissent une répartition équitable. Avec TCP BBR J'en tire également profit, car des mesures RTT plus réalistes permettent un meilleur rythme de transmission et un meilleur contrôle du cwnd. CUBIC réagit également de manière plus fluide lorsque je supprime les temps de mise en file d'attente excessifs. Ainsi, le débit augmente de manière organique, tandis que le Temps de réaction reste sous contrôle.

Virtualisation et piles cloud

Dans les machines virtuelles, plusieurs niveaux de mise en mémoire tampon s’additionnent : le QDisc invité, les files d’attente virtio/vhost, le QDisc hôte et la carte réseau physique. Je maintiens le TSQ actif dans l’invité et j’y définis une limite prudente afin qu’aucun pic important ne parvienne à l’hôte. Au niveau de l’hyperviseur, je veille à ce que les chaînes de latence restent courtes grâce à des QDiscs équitables, des anneaux TX modérés et un pinning d’IRQ propre. Le SR-IOV peut réduire la latence, mais transfère la responsabilité aux invités : sans TSQ dans l’invité, on risque de voir apparaître de longues files d’attente VF. Dans les conteneurs, le TSQ intervient par NetNS comme d’habitude ; grâce au cgroup pacing et aux limites CPU, j’empêche qu’un voisin bruyant ne fasse indirectement grimper la latence. Il est également important de prêter attention au coalescing et aux offloads dans le chemin virtio : un regroupement excessif allonge les accusés de réception, tandis qu’un regroupement insuffisant réduit l’efficacité – j’ajuste ces paramètres en fonction de l’objectif de latence, sans dogmatisme.

Wi-Fi et systèmes embarqués : bien gérer les cas particuliers

Sur les liaisons Wi-Fi, ce qui compte, c'est la Agrégation au niveau de la couche MAC. Si je laisse trop peu d’octets dans le chemin de transmission, le pilote ne peut regrouper qu’un nombre réduit de trames, ce qui réduit l’efficacité. Dans ce genre de configuration, j’augmente prudemment la limite et je vérifie le taux d’agrégation. Les plateformes OpenWrt et embarquées bénéficient également de chemins allégés dans les pilotes et d’opérations atomiques plus restreintes. Je teste chaque adaptation sous une charge radio réelle avant de Profil déployer largement.

Un monitoring et des métriques qui comptent vraiment

J'observe les RTT‑Je répartis les données par socket et je surveille les valeurs aberrantes, pas seulement les moyennes. À l’aide de ss, tc et d’exportateurs, je récupère les longueurs de file d’attente, les retransmissions ainsi que le taux de régulation (pacing_rate). Les programmes eBPF me signalent les événements lorsque les sockets sont limités puis à nouveau libérés. Le « Time-to-First-Byte » et les 95e et 99e centiles indiquent si le TSQ est efficace. Sans valeurs de mesure, toute Optimisation un vol à l'aveugle.

Tests A/B et tests de charge pertinents

Je mesure les effets TSQ de manière reproductible : d'abord une ligne de base sans modification, puis des balayages de paramètres isolés (par exemple 64, 96, 128, 192 Ko). Pour les charges de travail mixtes, j’exécute des flux parallèles (transferts en masse + nombreuses requêtes courtes) et je compare les 95e et 99e centiles des latences, et pas seulement la médiane. Même si j’interromps clairement les séries de tests (échauffement, fenêtre de mesure, refroidissement), des artefacts restent détectables. Je veille à ce que les constantes restent inchangées : mêmes modèles de charge utile, même route/MTU, mêmes fréquences de processeur serveur et client. Sur les liaisons WAN, je simule le délai, la gigue et les pertes à l’aide de tc netem, afin de vérifier si les limites TSQ ne plafonnent pas trop tôt lorsque le BDP est élevé. Ce n'est que lorsque les centiles se resserrent et que les retransmissions/pertes restent stables que j'intègre ces valeurs en production.

Optimisation matérielle et informations sur les pilotes

Je vérifie les paramètres TSO/GSO, le tampon circulaire de la carte réseau et la gestion des IRQ, afin que TSQ fonctionne correctement. Des anneaux TX trop grands allongent la file d’attente au niveau du périphérique ; trop petits, ils réduisent le taux d’utilisation. Un regroupement grossier des interruptions retarde les accusés de réception, tandis qu’un regroupement fin augmente la charge du processeur. J’adapte mon intervention en fonction de la pratique et, pour commencer, je renvoie à Coalescence d'interruption. L'objectif reste d'assurer une Latence avec un débit suffisant.

NUMA, RSS et affinité CPU

Des files d’attente courtes ne servent pas à grand-chose si les paquets traversent sans cesse les frontières NUMA. J’associe les files d’attente RX/TX via RSS/irqbalance aux cœurs du même domaine NUMA que celui sur lequel l’application s’exécute. Grâce à XPS/RPS, je contrôle quels processeurs prennent en charge le travail TX, évitant ainsi les sauts entre sockets. La réduction des échecs de cache et des conflits de verrouillage profite indirectement à TSQ : les confirmations de fin d’exécution reviennent plus rapidement, le socket est „ débridé “ plus tôt et les pics de latence sont évités. En cas de très nombreux flux par hôte, je prévois un nombre suffisant de files d’attente et j’évite que plusieurs flux « bruyants » n’entrent en collision sur le même anneau TX.

Étape par étape : vérifier si le TSQ est actif

Je commence par regarder Sysctl: La commande `sysctl net.ipv4.tcp_limit_output_bytes` affiche la limite actuelle. Ensuite, j'interroge `ss -tin` pour chaque socket, je surveille les valeurs de `send-q` et `rtt`, et je compare les phases de charge avec et sans ajustement de la limite. À l’aide d’iperf3, je génère une charge en arrière-plan et je mesure en parallèle les temps de réponse de l’API afin de mettre en évidence les priorités. La commande tc -s qdisc me fournit le nombre de paquets et de paquets perdus pour la discipline de sortie. Si les 95e et 99e centiles restent proches et que la CPU- Charge dans le cadre, ajuste le choix de la limite.

Erreurs courantes et anti-modèles

  • „ Plus de marge = plus de performances “ : cela vaut pour les tests de débit sans objectif de latence, mais ne tient pas la route pour les services interactifs. TSQ remplace les files d'attente surdimensionnées par un crédit adapté aux besoins de chaque flux.
  • „ Le TSQ réduit le débit “ : lorsqu'il est correctement configuré, le TSQ limite les pics de trafic, et non le débit moyen. Pour les charges de travail en masse, j'augmente modérément cette limite et je mesure les centiles plutôt que le seul débit de pointe en Mbit/s.
  • „ Le pacing suffit à lui seul “ : le lissage temporel est important, mais sans limiteur d’octets, les trames GSO volumineuses finissent tout de même par déborder dans le QDisc. Le TSQ et le pacing sont complémentaires.
  • „ Une valeur pour tous “ : les charges de travail, les liaisons et les cartes réseau diffèrent. Je travaille avec des plages de valeurs et je procède à une validation pour chaque environnement.
  • „ Seul le TCP est concerné “ : l'accent est mis sur le TCP, mais le système comporte d'autres paramètres de réglage (par exemple pour la charge UDP). J'empêche les protocoles parallèles d'engorger les mêmes files d'attente de manière incontrôlée.

Conclusion : une maîtrise ciblée de la latence

TSQ transfère le contrôle des files d'attente des pilotes vers le prise et réduit ainsi les encombrements directement à la source. Je limite le nombre d’octets mis en mémoire tampon par flux, ce qui garantit des accusés de réception rapides, un temps de transit (RTT) réduit et un partage équitable des files d’attente. Associé à fq_codel et à un contrôle de congestion moderne, le temps de réponse reste fiable même sous charge. Je traite les cas particuliers liés au Wi-Fi et aux systèmes embarqués à l’aide de limites adaptées et de tests en conditions réelles. En surveillant les indicateurs clés et en ajustant progressivement les limites, on maintient la Latence constamment faible, sans perte de débit inutile.

Derniers articles

Centre de données avec des baies de serveurs et une visualisation stylisée des données pour l'optimisation des performances de MySQL
Bases de données

Histogrammes MySQL – De meilleurs plans de requête sans index

Découvrez comment les histogrammes MySQL fournissent à l'optimiseur des statistiques précises, permettent d'élaborer de meilleurs plans de requête et améliorent considérablement l'optimisation de vos requêtes SQL sans avoir recours à des index supplémentaires.