Pourquoi un tube nommé est-il aussi lent que l'écriture dans un file?

J'essaie de comprendre comment les pipes nommées fonctionnent pour que je puisse rationaliser ma communication interprocess à sens unique. J'attends un peu de time en copiant datatables dans un buffer circulaire, ce que je pensais être stocké dans la RAM, donc je m'attendais à ce que le pipe soit beaucoup plus rapide que d'écrire dans un file.

Au lieu de cela, j'ai trouvé que le tuyau nommé (ou le tuyau anonyme) est à peu près la même vitesse qu'un file. Ceci est sur un bureau 3 GHz avec un lecteur de disque ordinaire (pas à l'état solide), exécutant Ubuntu Linux. Voici un programme de test simplifié en Python:

import sys import time import random megabyte = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for x in range(1024**2)) while True: before = time.time() sys.stdout.write(megabyte) after = time.time() sys.stderr.write("{} microseconds\n".format(1e6 * (after - before))) 

Tuyauterie directement dans /dev/null :

 python test.py > /dev/null 

donne 2,1 microsecondes (constante) pour chaque mégaoctet.

Tuyauterie dans un file:

 python test.py > /tmp/testout.txt 

sauts entre 500 microsecondes et 930 microsecondes (la plus grande valeur devient plus courante que le file devient plus grand — sans doute, il cherche l'espace disque).

Puis le tuyau nommé:

 mkfifo testpipe cat testpipe > /dev/null & python test.py > testpipe 

donne 640 microsecondes (constante) et un tuyau sans nom:

 python test.py | cat > /dev/null 

donne également 650 microsecondes (constante).

Quelqu'un peut-il expliquer pourquoi la vitesse du tuyau ressemble plus à la vitesse du file qu'à la vitesse de /dev/null ? Pourrais-je avoir un commutateur quelque part qui dit: «Exécuter des pipes à travers un tampon basé sur un file, plutôt qu'un tampon basé sur la memory vive», et puis-je changer ce commutateur? Pourrait-il s'agir d'une option kernel ou d'une variable shell?

Une autre interprétation: supposons que la sortie du disque saute entre 500 et 930 microsecondes parce que le 500 ne fait que canaliser et que le 930 est en train d'écrire. Alors le 500 ~ 640 pour la tuyauterie dans les deux cas est équivalent. Cependant, sous cette interprétation, pourquoi y a-t-il seulement un facteur de deux entre la tuyauterie et l'écriture réelle sur le disque? Les sites Web qui parlent de disques RAM disent que les disques RAM sont 50-200 fois plus rapides que les disques durs.

    Vous ne remarquez aucun avantage en termes de performances, car vous n'activez pas le disque lors de l'utilisation d'un file: datatables sont en cours d'apathement vers le disque, mais votre thread d'exécution n'a pas besoin d'attendre qu'il atterrisse. ne voyant pas réellement la pénalité de vitesse de bash le disque.

    Si vous voulez attendre que l'opération de disque soit terminée pour voir combien de time cela prend, appelez une sync() (vous pouvez voir la variation de votre version de python, voir ici ) – vous regarderez des dizaines de milliers de microsecondes juste pour votre disque à chercher quelques fois pour get le file écrit (en supposant qu'il n'a pas une sorte de cache d'écriture rapide comme dans un controller RAID).