Comment le kernel Linux gère-t-il les requêtes d’E / S asynchrones (AIO)?

J’écris un programme C pour lire des données à partir d’un disque SSD en lisant directement à partir du fichier de périphérique bloc brut.

linuxaio.h le Linux AIO (je parle de l’API Linux AIO, c’est-à-dire les fonctions fournies par linuxaio.h , telles que io_submit(...) etc., pas l’API POSIX AIO). J’ouvre le fichier de périphérique de bloc en utilisant le drapeau O_DIRECT et je m’assure que j’écris dans les tampons sont alignés sur la taille de bloc.

J’ai remarqué que Linux AIO, il est beaucoup plus rapide que d’utiliser Syncronous IO avec O_DIRECT drapeau O_DIRECT .

Ce qui m’a le plus surpris, c’est que le débit obtenu en lançant de nombreuses lectures aléatoires de quelques Ko chacune avec Linux AIO est remarquablement plus élevé que le débit atteint en lisant plusieurs Mo en utilisant des E / S synchrones et O_DIRECT .

Alors, j’aimerais savoir: comment se fait-il que Linux AIO fonctionne mieux que les E / S syncroneuses? Que fait le kernel lorsque AIO est utilisé? Le kernel effectue-t-il une demande de réordonnancement? L’utilisation de Linux AIO entraîne-t-elle une utilisation du processeur supérieure à celle des E / S synchrones?

Merci beaucoup d’avance

    Réponse courte: L’ implémentation AIO est très probablement plus rapide car elle soumet plusieurs E / S en parallèle, tandis que l’implémentation synchrone a zéro ou une E / S en vol. Cela n’a rien à voir avec l’écriture dans la mémoire ou avec le chemin d’E / S du kernel ayant une surcharge supplémentaire pour les E / S synchrones.

    Vous pouvez vérifier cela en utilisant iostat -x -d 1 . Regardez le fichier avgqu-sz (taille de la queue moyenne = nombre moyen d’E / S en vol) et % util (utilisation = pourcentage du temps pendant lequel le périphérique a reçu au moins une E / S).

    Longue réponse:

    • Le concept de “plus rapide” est délicat lorsque l’on parle d’E / S. Est-ce que “plus rapide” signifie une bande passante plus élevée? Ou est-ce que la latence est inférieure? Ou bande passante à une taille de requête donnée? Ou une latence à une profondeur de queue donnée? Ou une combinaison de latence, de bande passante, de taille de requête, de profondeur de queue et de nombreux autres parameters ou charges de travail? Je suppose ici que vous prenez en compte le débit / la bande passante, cependant, il est bon de se rappeler que les performances d’un périphérique de stockage ne sont pas une mésortingque de dimension unique.

    • Les SSD sont des périphériques hautement parallèles. Un SSD est composé de nombreuses puces flash, chaque puce ayant plusieurs dés qui peuvent lire / écrire indépendamment. Les SSD en profitent et effectuent de nombreuses E / S en parallèle, sans augmentation notable du temps de réponse. Par conséquent, en termes de débit, le nombre d’E / S simultanées détectées par le SSD est très important.

    • Comprenons ce qui se passe lorsqu’un thread soumet une E / S synchrone: a) le thread passe des cycles de CPU en préparant la requête d’E / S (générer des données, calculer un décalage, copier des données dans un tampon, etc.), b) l’appel système est effectuée (par exemple pread ()), l’exécution passe à l’espace kernel et les threads bloquent, c) la requête d’E / S est traitée par le kernel et traverse les différentes couches d’E / S du kernel, d) la demande d’E / S est soumise à l’appareil et traverse l’interconnexion (par exemple PCIe), e) la demande d’E / S est traitée par le micrologiciel SSD, f) la commande de lecture réelle est envoyée à la puce flash appropriée, g) le contrôleur SSD attend les données, h) le contrôleur SSD obtient les données de la puce flash et les envoie via l’interconnexion. À ce stade, les données quittent le SSD et les étapes ea) se produisent en sens inverse.

    • Comme vous pouvez le voir, le processus d’E / S synchrone lit la requête ping-pong avec le SSD. Pendant la plupart des étapes décrites ci-dessus, aucune donnée n’est réellement lue à partir des puces flash. De plus, bien que votre SSD puisse traiter des dizaines à des centaines de requêtes en parallèle, il détecte au plus une requête à un moment donné. Par conséquent, le débit est très faible car vous n’utilisez pas vraiment le SSD.

    • Les E / S asynchrones aident de deux manières: a) il permet au processus de soumettre plusieurs demandes d’E / S en parallèle (le SSD a suffisamment de travail pour restr occupé), et b) il permet de traiter les E / S par étapes donc découpler la latence de la phase du débit).

    • La raison pour laquelle les E / S asynchrones sont plus rapides que les E / S synchrones est que vous comparez des pommes et des oranges. Le débit synchrone se situe à une taille de requête donnée, à une faible profondeur de queue et sans traitement en pipeline. Le débit asynchrone a une taille de requête différente, une profondeur de queue supérieure et un traitement en pipeline. Les chiffres que vous avez vus ne sont pas comparables.

    • La majorité des applications intensives en E / S (c’est-à-dire la plupart des applications telles que les bases de données, les serveurs Web, etc.) ont de nombreux threads exécutant des E / S synchrones. Bien que chaque thread puisse soumettre au maximum une E / S à un moment donné, le kernel et le périphérique SSD voient de nombreuses demandes d’E / S pouvant être traitées en parallèle. Plusieurs demandes d’E / S de synchronisation génèrent les mêmes avantages que plusieurs requêtes d’E / S asynchrones.

      Les principales différences entre les E / S asynchrones et synchrones se résument à la planification des E / S et des processus et au modèle de programmation. Les E / S asynchrones et synchrones peuvent tous deux extraire les mêmes IOPS / débit d’un périphérique de stockage s’ils sont correctement exécutés.