44 votes

Accélération des E / S sur un fichier: mmap () vs. read ()

Toutes mes excuses si cela a été traité ailleurs et ma recherche n'a pas trouvé. Mmap-vs-lecture-blocs est un problème similaire à ce que je suis en train de travailler, et a fourni un bon point de départ sur ce problème, avec les discussions en mmap-vs-lire.

J'ai une application Linux qui lit de 150 à 200 fichiers (4-10 GO) en parallèle. Chaque fichier est lu à son tour dans les petites, de façon variable de la taille des blocs, généralement moins de 2K chaque. J'ai actuellement besoin pour maintenir plus de 200 MO/s en lecture taux combiné de l'ensemble des fichiers. Les disques de gérer ce bien. Il y a une exigence prévue de plus de 1 GB/s (ce qui est en dehors du disque de parvenir à l'heure actuelle).

Nous avons mis en place deux différents de lecture des systèmes à la fois de faire un usage intensif de l' posix_advise: la première est une mmaped lire en qui nous avons la carte de la totalité de l'ensemble de données et de lire sur demande. Le second est un read()/seek() en fonction du système.

Les deux fonctionnent très bien, mais seulement pour les cas modérés, l' read() méthode gère l'ensemble de notre fichier de cache beaucoup mieux et peut traiter ainsi avec 100s de GO de fichiers, mais il est mal limitée par la vitesse, mmap est en mesure de pré-en cache les données de prise de durablement le débit de données de plus de 200 mo/s facile à entretenir, mais ne peut pas traiter avec un grand total de l'ensemble de données de tailles.

Donc ma question vient à celles-ci:

A: Pouvez - read() type de fichier i/o sera encore optimisé au-delà de l' posix_advise des appels sur Linux, ou d'avoir à l'écoute du disque planificateur, VMM et posix_advise appels est que aussi bon que nous pouvons nous attendre?

B: il y a des méthodes systématiques pour mmap pour mieux faire face à de très grandes données cartographiées?

14voto

Matt Joiner Points 29194

Lit arrière à quoi? Quelle est la destination finale de ces données?

Depuis on dirait que vous vous êtes complètement IO lié, mmap et read devrait pas faire de différence. La partie intéressante est de savoir comment vous obtenez les données de votre récepteur.

En supposant que vous êtes de mettre ces données à un tuyau, je recommande que vous venez de vider le contenu de chaque fichier dans son intégralité dans le tuyau. Pour ce faire, à l'aide de zéro-copie, essayez de l' splice appel système. Vous pourriez également essayer de copier le fichier manuellement, ou bifurquer une instance d' cat ou un autre outil qui peut mettre en mémoire tampon fortement avec le fichier en cours comme stdin, et le conduit de sortie standard (stdout).

if (pid = fork()) {
    waitpid(pid, ...);
} else {
    dup2(dest, 1);
    dup2(source, 0);
    execlp("cat", "cat");
}

Update0

Si votre traitement est fichier-agnostique, et ne nécessite pas d'accès aléatoire, vous souhaitez créer un pipeline à l'aide des options décrites ci-dessus. Votre étape de traitement doit accepter des données provenant de l'entrée standard, ou un tuyau.

Pour répondre à vos questions plus spécifiques:

A: Peut lire() type de fichier i/o sera encore optimisé au-delà de la posix_advise appels sur Linux, ou d'avoir à l'écoute du disque planificateur, VMM et posix_advise appels est que aussi bon que nous pouvons nous attendre?

C'est aussi bon qu'il obtient dire le noyau à partir de l'espace utilisateur. Le reste est à vous: mise en mémoire tampon, le filetage, etc. mais c'est dangereux et probablement peu rentable deviner. Je venais de passer avec épissage les fichiers dans un tuyau.

B: il y a des méthodes systématiques pour mmap pour mieux faire face à de très grandes données cartographiées?

Oui. Les options suivantes peuvent vous donner des performances impressionnantes prestations (et peut rendre mmap de dollars à l'aide de plus de lire, avec les tests):

  • MAP_HUGETLB Allouer de la cartographie à l'aide de "huge pages".

    Cela permettra de réduire la pagination de frais généraux dans le noyau, ce qui est excellent si vous serez cartographie gigabyte de la taille des fichiers.

  • MAP_NORESERVE Ne pas réserver de l'espace de swap pour ce mappage. Lorsque l'espace d'échange est réservé, on a la garantie qu'il est possible de modifier la cartographie. Lorsque l'espace de swap n'est pas réservé d'un SIGSEGV sur une écriture si aucune mémoire physique disponible.

    Cela vous évitera de manquer de mémoire tout en gardant votre mise en œuvre simple, si vous n'avez pas assez de mémoire physique + swap pour l'ensemble de la cartographie.**

  • MAP_POPULATE Remplit les tables de pages pour une correspondance. Pour un fichier de mappage, ce qui provoque de cache en lecture sur le fichier. Plus tard, accède à la cartographie ne sera pas bloqué par des défauts de page.

    Cela peut vous donner speed-ups avec des ressources matérielles suffisantes, et si le pré-chargement est commandé, et paresseux. Je soupçonne que ce drapeau est redondant, le VFS probablement ne fait mieux par défaut.

4voto

Basile Starynkevitch Points 67055

Utiliser l’appel système readahead pourrait peut-être aider, si votre programme peut prédire à l’avance les fragments de fichier qu’il veut lire (mais ce n’est qu’une hypothèse, je pourrais me tromper).

Et je pense que vous devriez ajuster votre application, et peut-être même vos algorithmes, pour lire des données beaucoup plus volumineuses que quelques kilo-octets. Ne peut pas être un demi-mégaoctet à la place?

1voto

Tobias Schlegel Points 3219

Ici, le problème ne semble pas être ce qui l'api est utilisée. Il n'a pas d'importance si vous utilisez mmap() ou lire(), le disque a encore de chercher à le point spécifié et lire les données (même si le système d'exploitation ne aider à optimiser l'accès).

mmap() a des avantages sur read() si vous lisez très petits morceaux (quelques octets) parce que vous n'avez pas d'appels du système d'exploitation pour chaque morceau, qui devient très lent.

Je conseille comme Basile fait de lire plus de 2 ko, consécutivement, de sorte que le disque n'a pas à chercher très souvent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X