SysadminNews

Des patchs MM Linux affichent jusqu'à 12,8x sur gup_test

Sur cette page
  1. La fonction, et le problème arithmétique
  2. Qui paie réellement ce coût
  3. Comment lire ce 12,8x
  4. La suite
  5. Sources et pour aller plus loin

Rik van Riel a publié une série de patchs en appel à commentaires qui apprend à l'une des fonctions les moins glorieuses du noyau Linux à cesser de tout traiter une page à la fois. La fonction est follow_page_mask, celle qui transforme une adresse virtuelle en la struct page qui la porte, et elle parcourt aujourd'hui les tables de pages pour chaque page prise isolément. Les patchs de van Riel permettent à un parcours de renvoyer plusieurs pages par appel. Le banc d'essai gup_test du noyau rapporte des gains allant jusqu'à 12,8x. Si vous épinglez de la mémoire pour de l'affectation de périphérique, du RDMA ou des tampons enregistrés, c'est le chemin de code sous l'attente que vous avez appris à tolérer.

The short answer

L'ingénieur de Meta Rik van Riel a publié une série en appel à commentaires qui regroupe les recherches dans le follow_page_mask du noyau Linux, permettant aux parcours de tables de pages de renvoyer plusieurs pages par appel au lieu d'en résoudre une seule à la fois. Le principal bénéficiaire est get_user_pages, le chemin derrière l'épinglage mémoire pour l'affectation de périphérique VFIO, le RDMA et les tampons enregistrés. Le banc gup_test rapporte jusqu'à 12,8x.

12,8xmeilleure amélioration rapportée sur gup_test
1page par appel, dans le code tel qu'il est aujourd'hui
RFCstatut, donc la conception peut encore évoluer
Carte réponse décrivant la série de patchs en appel à commentaires de Rik van Riel, qui regroupe les recherches dans la fonction follow_page_mask du noyau Linux afin que les parcours de tables de pages renvoient plusieurs pages par appel, au bénéfice des appelants de get_user_pages, le banc d'essai gup_test du noyau rapportant des améliorations allant jusqu'à 12,8 fois.
Ce que change la série de patchs, et ce qu'elle a mesuré. Source : Phoronix, 11 août 2026. PNG

Certaines optimisations du noyau intéressent parce qu'elles sont astucieuses. Celle-ci intéresse par son évidence rétrospective, ce qui est généralement le signe que la difficulté se situait ailleurs que dans l'idée.

Rik van Riel, ingénieur chez Meta et vétéran de la gestion mémoire de Linux, a publié une série en appel à commentaires qui modifie le comportement de follow_page_mask. Aujourd'hui, elle résout une page par appel. Ses patchs permettent à un parcours de tables de pages d'en renvoyer plusieurs. Le banc d'essai gup_test du noyau montre des améliorations allant jusqu'à 12,8x.

La fonction, et le problème arithmétique

follow_page_mask traduit une adresse virtuelle en la struct page qui la porte. Pour cela, elle parcourt les tables de pages, en descendant de niveau en niveau jusqu'à l'entrée recherchée.

Vous ne l'appellerez presque jamais vous-même. Vous en dépendez en permanence, parce qu'elle se trouve sous get_user_pages, l'interface qu'emploie le noyau chaque fois qu'il lui faut les pages physiques réelles derrière un tampon de l'espace utilisateur, et pas seulement une plage d'adresses.

Le problème n'est pas qu'un parcours isolé soit lent. C'est qu'un parcours résout exactement une page, si bien qu'épingler un grand tampon impose de refaire ce parcours une fois par page, alors que des pages consécutives résident très souvent dans la même zone de la même table. Chaque parcours redescend des niveaux que le précédent venait de visiter, arrive une entrée plus loin, et repart. Puis l'appel suivant recommence depuis le sommet.

Le regroupement supprime cette répétition. Si le parcours a déjà atteint une table contenant une suite de pages voulues par l'appelant, autant lui rendre la suite entière.

Qui paie réellement ce coût

Les appelants qui comptent sont ceux qui épinglent de la mémoire utilisateur pour qu'autre chose que le processeur puisse l'atteindre.

L'affectation de périphérique VFIO. Donner à une machine virtuelle un accès direct à un GPU ou à une carte réseau suppose d'épingler la mémoire de l'invité pour que le périphérique puisse y faire du DMA en sécurité. Sur un invité doté d'une grande allocation mémoire, cet épinglage est une pause réelle et mesurable au démarrage.

Le RDMA. Les régions mémoire sont enregistrées à l'avance pour qu'un hôte distant y écrive sans solliciter le processeur local. L'enregistrement épingle les pages, et le coût tombe à la création d'une paire de files plutôt que pendant les transferts que tout le monde mesure.

Les tampons enregistrés d'io_uring, les entrées-sorties directes et divers chemins DMA, pour la même raison de fond.

La forme commune mérite d'être nommée : ce sont des coûts de mise en place, payés en gros blocs, à des moments que les utilisateurs remarquent. Un invité qui démarre. Une tâche qui se planifie. Une connexion qui s'établit. Personne ne les profile parce qu'ils ne sont pas dans le régime permanent, et tout le monde les attend.

Carte comparative montrant le comportement actuel où chaque itération de get_user_pages effectue un parcours complet des tables de pages pour résoudre une seule page, à côté du comportement regroupé où un parcours résout une suite de pages contiguës et les renvoie ensemble à l'appelant.
Un parcours par page, face à un parcours par suite de pages. Illustration simplifiée de l'approche décrite dans la série de patchs. PNG

Comment lire ce 12,8x

Avec prudence, et avec respect pour ce que le chiffre est.

gup_test est un programme de l'arbre du noyau écrit pour solliciter get_user_pages et les chemins de gestion mémoire voisins. Il existe pour faire chauffer ce code afin que les développeurs le mesurent. C'est exactement ce qui rend le chiffre utile en relecture et trompeur en titre.

Une amélioration de 12,8x sur gup_test signifie que le chemin optimisé est devenu nettement plus rapide. Cela ne signifie pas qu'une charge réelle accélère de 12,8x, parce qu'aucune charge réelle ne passe tout son temps dans get_user_pages. Ce que vous constateriez dépend de la part de votre temps écoulé passée dans cette fonction, laquelle est nulle pour la plupart des logiciels, et représente une fraction réellement intéressante pour un hôte qui épingle des dizaines de gigaoctets pour de l'affectation de périphérique.

C'est la bonne façon de tenir les chiffres de bancs d'essai issus de patchs RFC en général. La mesure donne le plafond, votre profilage donne la part.

La suite

RFC signifie que l'auteur demande si l'approche est la bonne, pas qu'il propose une intégration. La relecture en gestion mémoire est lente par conception, parce qu'une erreur ici ne produit pas un bogue dans un sous-système, elle produit de la corruption n'importe où. Attendez-vous à des révisions.

Il y a aussi un schéma plus large à noter. Beaucoup de travaux récents sur le noyau consistent à retirer du surcoût par élément dans des chemins conçus quand les éléments étaient moins nombreux et plus petits, que ce soit Linux 7.3 qui laisse les applications réclamer la VRAM promise ou les correctifs d'équilibrage de charge par cluster sur les processeurs hybrides Intel. Les machines ont beaucoup grossi. Le code qui itère une fois par unité n'a pas toujours suivi.

Si le coût d'épinglage mémoire façonne aujourd'hui la façon dont vous concevez quelque chose, l'enseignement utile n'est pas un numéro de version. C'est que la contrainte fait l'objet d'un travail actif, et qu'elle mérite d'être remesurée dans un an.

Sources et pour aller plus loin

Questions fréquentes

Qu'est-ce que follow_page_mask et pourquoi devrais-je m'en soucier ?

C'est la fonction du noyau qui traduit une adresse virtuelle en la struct page qui la porte, en parcourant les tables de pages niveau par niveau. Presque rien ne l'appelle directement, d'où son côté méconnu, mais une grande partie du noyau en dépend indirectement via get_user_pages. Chaque fois que le noyau a besoin des pages physiques derrière un tampon de l'espace utilisateur, et pas seulement des adresses, c'est grosso modo ce chemin qui est emprunté. La raison pour laquelle cela compte aujourd'hui est arithmétique : elle résout une page par appel, donc un grand tampon signifie un très grand nombre d'appels, chacun répétant un parcours qui redécouvre pour l'essentiel ce que le précédent avait trouvé.

Que changent exactement ces patchs ?

Ils permettent à un parcours de tables de pages de renvoyer plusieurs pages par appel. Au lieu de demander une page, d'obtenir une page et de recommencer le parcours depuis le sommet pour la suivante, un appelant peut recevoir une suite de pages que le parcours a déjà résolues. Le travail est une série en appel à commentaires, ce qui signifie en langage noyau que l'auteur sollicite une relecture de l'approche plutôt qu'une intégration. Van Riel est un ingénieur de Meta avec un long passé en gestion mémoire, donc la série pèse, mais RFC est une étiquette réelle et la conception peut encore changer substantiellement avant que quoi que ce soit n'atterrisse.

D'où vient le chiffre de 12,8x, et comment le lire ?

De gup_test, un programme présent dans l'arbre du noyau écrit spécifiquement pour solliciter get_user_pages et les chemins de gestion mémoire associés. Phoronix rapporte des gains allant jusqu'à 12,8x sur ce banc d'essai avec les patchs RFC appliqués. Lisez-le comme une mesure de la fonction isolée, pas comme une prédiction pour votre charge de travail. gup_test est conçu pour marteler précisément le code optimisé, ce qui le rend utile au développeur et trompeur s'il est cité comme un chiffre système. Le résumé honnête est qu'une boucle interne chaude est devenue nettement plus rapide, et que la part qui vous parvient dépend entièrement du temps que vous y passiez.

Quelles charges réelles reposent sur get_user_pages ?

Celles qui exigent que le noyau épingle de la mémoire utilisateur pour qu'autre chose que le processeur puisse l'atteindre. L'affectation de périphérique via VFIO, qui donne à une machine virtuelle un accès direct à un GPU ou à une carte réseau. Le RDMA, où un hôte distant écrit dans de la mémoire enregistrée à l'avance. Les tampons enregistrés d'io_uring. Les chemins d'entrées-sorties directes. Divers montages DMA. Leur point commun est d'épingler de vastes régions au moment de la mise en place, si bien que le coût se manifeste comme une pause au démarrage d'un invité, à la création d'une paire de files, ou à l'enregistrement d'un jeu de tampons. Ce sont exactement les moments que ce travail vise.

Quand cela arriverait-il dans un noyau que je peux exploiter ?

Pas de sitôt, et avancer une version précise relèverait de la devinette. Une série RFC est le début de la conversation de relecture, pas sa fin. Les patchs de gestion mémoire sont tenus à une exigence élevée parce que le rayon d'explosion d'une erreur est le système entier, donc le chemin réaliste passe par plusieurs révisions en réponse aux relectures, puis une fenêtre d'intégration, puis ce que la politique de noyau de votre distribution autorise. La raison d'en avoir connaissance aujourd'hui relève de la planification, pas du déploiement. Si le coût d'épinglage façonne actuellement votre architecture, il est utile de savoir que la contrainte est travaillée plutôt que figée.