(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 exemplefsync
(>=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 aulibaio
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éclareio_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 surio_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 lethreads
etaio
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 leio_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 duio_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 (nonio_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 sonio_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 PostgreSQLio_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 leliburing
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 pasliburing
. - Le noyau initial de Fedora 32 est 5.6 et il a un
liburing
empaqueté doncio_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 leliburing
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 chargeio_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().