GNU/Linux >> Tutoriels Linux >  >> Linux

N'y a-t-il vraiment pas d'E/S de blocs asynchrones sous Linux ?

(2020) Si vous utilisez un noyau Linux 5.1 ou supérieur, vous pouvez utiliser le io_uring interface pour les E/S de type fichier et obtenir un excellent fonctionnement asynchrone.

Par rapport aux libaio existants /Interface KAIO, io_uring présente les avantages suivants :

  • Conserve le comportement asynchrone lors des E/S tamponnées (et pas seulement lors des E/S directes)
  • Plus facile à utiliser (surtout avec le liburing bibliothèque d'assistance)
  • Peut éventuellement fonctionner de manière interrogée (mais vous aurez besoin de privilèges plus élevés pour activer ce mode)
  • Moins d'espace de comptabilité par E/S
  • Réduction de la surcharge du processeur en raison du nombre réduit de commutateurs de mode d'appel système de l'espace utilisateur/du noyau (un gros problème de nos jours en raison de l'impact des atténuations du spectre/de l'effondrement)
  • Les descripteurs de fichiers et les tampons peuvent être préenregistrés pour gagner du temps lors du mappage/démappage
  • Plus rapide (peut atteindre un débit global plus élevé, les E/S ont une latence plus faible)
  • Le "mode lié" peut exprimer des dépendances entre les E/S (>=noyau 5.3)
  • Peut fonctionner avec des E/S basées sur des sockets (recvmsg() /sendmsg() sont pris en charge à partir de>=5.3, voir les messages mentionnant le mot support dans l'historique git de io_uring.c)
  • Prend en charge les tentatives d'annulation des E/S en file d'attente (>=5.5)
  • Peut demander cette E/S toujours être exécuté à partir d'un contexte asynchrone plutôt que la valeur par défaut consistant à ne revenir qu'à des E/S de punting vers un contexte asynchrone lorsque le chemin de soumission en ligne déclenche le blocage (> =noyau 5.6)
  • Compatibilité croissante avec l'exécution d'opérations asynchrones au-delà de read /write (par exemple fsync (>=5.1), fallocate (>=5.6), splice (>=5.7) et plus)
  • Dynamique de développement plus élevé
  • Ne devient pas bloquant chaque fois que les étoiles ne sont pas parfaitement alignées

Comparé au POSIX AIO de la glibc, io_uring présente les avantages suivants :

  • Beaucoup plus rapide et plus efficace (les avantages de frais généraux réduits ci-dessus s'appliquent encore plus ici)
  • L'interface est basée sur le noyau et N'UTILISE PAS de pool de threads d'espace utilisateur
  • Moins de copies des données sont faites lors des E/S mises en mémoire tampon
  • Pas de lutte avec les signaux
  • POSIX AIO de Glibc ne peut pas avoir plus d'une E/S en vol sur un seul descripteur de fichier alors que io_uring peut certainement !

Le document Efficient IO with io_uring donne beaucoup plus de détails sur io_uring les avantages et l'utilisation. Le document Quoi de neuf avec io_uring décrit les nouvelles fonctionnalités ajoutées à io_uring entre les noyaux 5.2 - 5.5, tandis que l'article sur la croissance rapide de io_uringLWN décrit les fonctionnalités disponibles dans chacun des noyaux 5.1 - 5.5 avec un aperçu de ce qui allait être dans 5.6 (voir également la liste des articles io_uring de LWN). Il y a aussi une présentation vidéo Faster IO via io_uring Kernel Recipes (diapositives) de fin 2019 et Quoi de neuf avec io_uring Kernel Recipes présentation vidéo (diapositives) à partir de la mi-2022 par io_uring l'auteur Jens Axboe. Enfin, le tutoriel Lord of the io_uring donne une introduction à io_uring utilisation.

Le io_uring La communauté peut être contactée via la liste de diffusion io_uring et les archives de la liste de diffusion io_uring montrent le trafic quotidien au début de 2021.

Re "prise en charge des E/S partielles au sens de recv() contre read() " :un correctif est entré dans le noyau 5.3 qui réessayera automatiquement io_uring des lectures courtes et un autre commit sont entrés dans le noyau 5.4 qui modifie le comportement pour ne prendre en charge automatiquement que les lectures courtes lorsque vous travaillez avec des fichiers "normaux" sur des requêtes qui n'ont pas défini le REQ_F_NOWAIT flag (il semble que vous puissiez demander REQ_F_NOWAIT par IOCB_NOWAIT ou en ouvrant le fichier avec O_NONBLOCK ). Ainsi, vous pouvez obtenir recv() style- comportement d'E/S "court" à partir de io_uring aussi.

Logiciel/projets utilisant io_uring

Bien que l'interface soit jeune (sa première incarnation est arrivée en mai 2019), certains logiciels open source utilisent io_uring "dans la nature":

  • fio (qui est également écrit par Jens Axboe) a un moteur io_uring ioengine (en fait, il a été introduit dans fio-3.13 à partir de février 2019 !). La présentation "Amélioration des performances de stockage à l'aide de la nouvelle interface d'E/S du noyau Linux SNIA" (diapositives) de deux ingénieurs Intel indique qu'ils ont pu obtenir le double d'IOPS sur une charge de travail et moins de la moitié de la latence moyenne à une profondeur de file d'attente de 1 sur une autre charge de travail lors de la comparaison des io_uring ioengine au libaio ioengine sur un appareil Optane.
  • Le projet SPDK a ajouté la prise en charge de l'utilisation de io_uring (!) pour bloquer l'accès aux périphériques dans sa version v19.04 (mais il ne s'agit évidemment pas du backend pour lequel vous utiliseriez généralement SPDK autre que l'analyse comparative). Plus récemment, ils semblent également avoir ajouté la prise en charge de son utilisation avec les sockets dans la v20.04...
  • Ceph a validé un backend io_uring en décembre 2019 qui faisait partie de sa version 15.1.0. L'auteur du commit a posté un commentaire github montrant que certains backend io_uring ont des gains et des pertes par rapport au backend libaio (en termes d'IOPS, de bande passante et de latence) en fonction de la charge de travail.
  • RocksDB a commis un io_uring backend pour MultiRead en décembre 2019 et faisait partie de sa version 6.7.3. Jens déclare io_uring a contribué à réduire considérablement la latence.
  • libev a publié la 4.31 avec un io_uring initial backend en décembre 2019. Alors que certains des points originaux de l'auteur ont été abordés dans les nouveaux noyaux, au moment de la rédaction (mi-2021), l'auteur de libev a quelques mots de choix sur io_uring de maturité et adopte une approche attentiste avant de mettre en œuvre d'autres améliorations.
  • QEMU a engagé un backend io_uring en janvier 2020 et faisait partie de la version 5.0 de QEMU. Dans la présentation PDF "io_uring in QEMU :high-performance disk IO for Linux", Julia Suvorova montre le io_uring backend surpassant le threads et aio backends sur une charge de travail de blocs aléatoires de 16 000 blocs.
  • Samba a fusionné un io_uring Backend VFS en février 2020 et faisait partie de la version Samba 4.12. Dans le "Backend Linux io_uring VFS." Fil de la liste de diffusion Samba, Stefan Metzmacher (l'auteur du commit) dit le io_uring module a été capable de pousser environ 19 % de débit en plus (par rapport à un backend non spécifié) dans un test synthétique. Vous pouvez également lire la présentation PDF "Async VFS Future" de Stefan pour une partie de la motivation derrière les changements.
  • Libunifex C++ expérimental de Facebook l'utilise (mais vous aurez également besoin d'un noyau 5.6+)
  • Les gens de la rouille ont écrit des wrappers pour faire io_uring plus accessible à la rouille pure. rio est une bibliothèque dont on parle un peu et l'auteur dit qu'ils ont atteint un débit plus élevé par rapport à l'utilisation d'appels de synchronisation enveloppés dans des threads. L'auteur a fait une présentation sur sa base de données et sa bibliothèque au FOSDEM 2020 qui comprenait une section vantant les vertus du io_uring .
  • La bibliothèque de rouille Glommio utilise exclusivement io_uring . L'auteur (Glauber Costa) a publié un document intitulé Le stockage moderne est très rapide. Ce sont les API qui sont mauvaises, montrant qu'avec un réglage minutieux, Glommio pourrait obtenir plus de 2,5 fois les performances par rapport à la normale (non io_uring ) appels système lors de l'exécution d'E/S séquentielles sur un appareil Optane.
  • Gluster a fusionné un io_uring posix xlator en octobre 2020 et faisait partie de la version Gluster 9.0. L'auteur du commit mentionne que les performances n'étaient "pas pires que les appels système pwrite/preread normaux".

Logiciel d'investigation utilisant io_uring

  • Andres Freund, développeur PostgreSQL, a été l'une des forces motrices derrière io_uring améliorations (par exemple, la solution de contournement pour réduire les conflits d'inodes du système de fichiers). Il existe une présentation "E/S asynchrones pour PostgreSQL" (attention, la vidéo est interrompue jusqu'à la minute 5) (PDF) motivant la nécessité de modifications de PostgreSQL et démontrant certains résultats expérimentaux. Il a exprimé l'espoir d'obtenir son io_uring facultatif prise en charge dans PostgreSQL 14 et semble parfaitement conscient de ce qui fonctionne et ne fonctionne pas, même au niveau du noyau. En décembre 2020, Andres discute plus en détail de son PostgreSQL io_uring travail dans le fil de la liste de diffusion pgsql-hackers "Blocking I/O, async I/O and io_uring" et mentionne que le travail en cours peut être vu sur https://github.com/anarazel/postgres/tree/aio .
  • Le projet Netty dispose d'un dépôt d'incubateur fonctionnant sur io_uring support nécessitant un noyau 5.9
  • libuv a une demande d'extraction à son encontre en ajoutant io_uring soutien, mais sa progression dans le projet a été lente
  • SwiftNIO a ajouté io_uring prise en charge des événements (mais pas des appels système) en avril 2020 et Linux :le problème d'E/S io_uring complet décrit les plans pour l'intégrer davantage
  • Le projet Tokio Rust a développé une preuve de concept tokio-uring

Prise en charge de la distribution Linux pour io_uring

  • (Fin 2020) Le dernier noyau d'activation HWE d'Ubuntu 18.04 est 5.4 donc io_uring les appels système peuvent être utilisés. Cette distribution ne pré-emballe pas le liburing bibliothèque d'assistance, mais vous pouvez la créer vous-même.
  • Le noyau initial d'Ubuntu 20.04 est 5.4 donc io_uring les appels système peuvent être utilisés. Comme ci-dessus, la distribution ne pré-emballe pas liburing .
  • Le noyau initial de Fedora 32 est 5.6 et il a un liburing empaqueté donc io_uring est utilisable.
  • SLES 15 SP2 a un noyau 5.3 donc io_uring les appels système peuvent être utilisés. Cette distribution ne pré-emballe pas le liburing bibliothèque d'assistance, mais vous pouvez la créer vous-même.
  • (Mi-2021) Le noyau par défaut de RHEL 8 ne le fait pas prend en charge io_uring (une version précédente de cette réponse a dit à tort que c'était le cas). Il existe un article de la base de connaissances Red Hat Add io_uring support (le contenu se trouve derrière un paywall d'abonné) qui est "en cours".
  • (Mi 2022) Le noyau par défaut de RHEL 9 ne le fait pas prend en charge io_uring . Le noyau est assez récent (5.14) mais prend en charge io_uring est explicitement désactivé.

Espérons que io_uring inaugurera une meilleure histoire d'E/S de type fichier asynchrone pour Linux.

(Pour ajouter un mince placage de crédibilité à cette réponse, à un moment donné dans le passé Jens Axboe (mainteneur de la couche de bloc du noyau Linux et inventeur de io_uring ) a pensé que cette réponse pourrait valoir la peine d'être votée :-)


La vraie réponse, qui a été indirectement pointée par Peter Teoh, est basée sur io_setup() et io_submit(). Plus précisément, les fonctions "aio_" indiquées par Peter font partie de l'émulation glibc au niveau utilisateur basée sur les threads, ce qui n'est pas le cas. une mise en œuvre efficace. La vraie réponse est dans :

io_submit(2)
io_setup(2)
io_cancel(2)
io_destroy(2)
io_getevents(2)

Notez que la page de manuel, datée du 2012-08, indique que cette implémentation n'a pas encore mûri au point de pouvoir remplacer l'émulation de l'espace utilisateur glibc :

http://man7.org/linux/man-pages/man7/aio.7.html

cette implémentation n'a pas encore mûri au point où l'implémentation POSIXAIO peut être complètement réimplémentée à l'aide des appels kernelsystem.

Ainsi, selon la dernière documentation du noyau que je peux trouver, Linux n'a pas encore de modèle d'E/S asynchrone basé sur le noyau. Et, si je suppose que le modèle documenté est réellement mature, il ne prend toujours pas en charge les E/S partielles dans le sens de recv() vs read().


Linux
  1. Rapports d'E/S à partir de la ligne de commande Linux

  2. Linux - Détermination du fichier spécifique responsable des E/S élevées ?

  3. N Équivalent à Top Mais pour les E/S réseau ?

  4. Confusion à propos du mécanisme d'E/S asynchrone interne de node.js

  5. Quel est l'équivalent Unix/Linux des E/S enregistrées ?

10 Commande Linux iostat pour rapporter les statistiques du CPU et des E/S

Linux – Comment surveiller les E/S de disque dans un répertoire particulier ?

10 exemples iozone pour la mesure des performances d'E/S de disque sous Linux

Comment purger les caches d'E/S disque sous Linux ?

Linux :Existe-t-il quelque chose de similaire à top pour les E/S ?

Baisse massive et imprévisible des performances d'E/S sous Linux