Le mappage de la mémoire d'un fichier évite directement la copie des tampons qui se produisent avec read()
et write()
appels. Appels au read()
et write()
inclure un pointeur vers le tampon dans l'espace d'adressage du processus où les données sont stockées. Le noyau doit copier les données vers/depuis ces emplacements. Utilisation de mmap()
mappe le fichier à l'espace d'adressage du processus, afin que le processus puisse adresser le fichier directement et qu'aucune copie ne soit requise.
Il n'y a pas non plus de surcharge d'appel système lors de l'accès au fichier mappé en mémoire après l'appel initial si le fichier est chargé en mémoire au mmap()
initial . Si une page du fichier mappé n'est pas en mémoire, l'accès générera une erreur et demandera au noyau de charger la page en mémoire. Lecture d'un gros bloc avec read()
peut être plus rapide que mmap()
dans ce cas, si mmap()
générerait un nombre important d'erreurs pour lire le fichier. (Il est possible de prévenir le noyau à l'avance avec madvise()
afin que le noyau puisse charger les pages à l'avance avant l'accès).
Pour plus de détails, il y a une question connexe sur Stack Overflow :mmap() vs blocs de lecture
Premièrement, dans la plupart des opérations d'E/S, les caractéristiques du matériel de stockage sous-jacent dominent les performances. Une matrice RAID5 mal configurée de vingt-neuf disques SATA S-L-O-W 5400 tr/min sur un système lent et manquant de mémoire utilisant S/W RAID avec des tailles de bloc incompatibles et des systèmes de fichiers mal alignés vous donnera des performances médiocres par rapport à un système correctement configuré et aligné. SSD RAID 1+0 sur un contrôleur hautes performances malgré tout réglage logiciel que vous pourriez essayer.
Mais le seul moyen mmap()
peut être beaucoup plus rapide si vous lisez les mêmes données plus d'une fois et les données que vous lisez ne sont pas paginées entre les lectures en raison de la pression de la mémoire.
Étapes de la carte mémoire :
- Appel système pour créer des mappages virtuels - très coûteux
- Le processus accède à la mémoire pour la première fois, ce qui provoque un défaut de page - coûteux (et peut devoir être répété s'il est paginé)
- Le processus lit réellement la mémoire
Si le processus n'effectue les étapes 2 et 3 qu'une seule fois pour chaque bit de données lu, ou si les données sont supprimées de la mémoire en raison de la pression de la mémoire, mmap()
va être plus lent.
read()
étapes :
- L'appel système copie les données du disque vers le cache de la page (il peut y avoir ou non un défaut de page, les données peuvent déjà être dans le cache de la page, ce qui l'ignore)
- Données copiées du cache de pages vers la mémoire de traitement (erreur de page ou non)
Le mappage de la mémoire ne fera que battre cette performance en raison de cette copie supplémentaire du cache de page pour traiter la mémoire. Mais une simple copie d'une page de mémoire (ou moins) doit être faite plusieurs fois pour battre le coût de configuration du mappage - probablement. Combien de fois dépend de votre système. La bande passante mémoire, la façon dont l'ensemble de votre système est utilisé, tout. Par exemple, si le temps utilisé par la gestion de la mémoire du noyau pour configurer le mappage n'aurait de toute façon été utilisé par aucun autre processus, le coût de création du mappage n'est vraiment pas très élevé. Inversement, si vous avez beaucoup de traitement sur votre système qui implique beaucoup de création/destruction de mappage de mémoire virtuelle (c'est-à-dire, beaucoup de processus de courte durée), l'impact des E/S mappées en mémoire peut être significatif.
Ensuite, il y a read()
en utilisant les E/S directes :
- Appel système pour lire du disque dans l'espace mémoire du processus. (peut ou non provoquer une erreur de page)
Les lectures d'E/S directes sont pratiquement impossibles à battre en termes de performances. Mais vous devez vraiment ajuster vos modèles d'E/S à votre matériel pour optimiser les performances.
Notez qu'un processus peut à peu près contrôler si la lecture de données provoque une erreur de page pour le tampon que le processus utilise pour lire.
Alors, l'accès aux fichiers mappés en mémoire est-il plus rapide ? Peut-être que oui, peut-être que non.
Cela dépend de votre ou vos modèles d'accès. Avec votre matériel et tout le reste dans vos chemins d'E/S.
Si vous diffusez un fichier vidéo de 30 Go sur une machine avec 4 Go de RAM et que vous ne revenez jamais en arrière et ne relisez aucune des données, le mappage de la mémoire du fichier est probablement le pire façon de le lire.
Inversement, si vous disposez d'une table de recherche de 100 Mo pour certaines données auxquelles vous accédez au hasard des milliards et des milliards de fois dans votre traitement et suffisamment de mémoire pour que le fichier ne soit jamais paginé, le mappage de la mémoire écrasera toutes les autres méthodes d'accès.
Un énorme avantage des fichiers mappés en mémoire
Les fichiers de mappage de mémoire présentent un énorme avantage par rapport aux autres formes d'E/S :la simplicité du code. Il est vraiment difficile de battre la simplicité d'accès à un fichier comme s'il était en mémoire. Et la plupart du temps, la différence de performances entre le mappage en mémoire d'un fichier et l'exécution d'opérations d'E/S discrètes n'est pas si importante de toute façon.