Pourquoi ma fonction “chat” avec les appels système est-elle plus lente par rapport au “chat” de Linux?

J’ai fait cette fonction en C en utilisant les appels système (open, read et write) pour simuler la fonction “cat” dans les systèmes Linux et c’est plus lent que le vrai …

J’utilise la même taille de mémoire tampon que le vrai “chat” et en utilisant “strace” Je pense qu’il fait le même nombre d’appels système. Mais la sortie de mon “chat” est un peu plus lente que le vrai “chat”.

C’est le code que j’ai:

#define BUFSIZ 32768 int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) { ssize_t writtenBytes = 0; while(writtenBytes  0); return 0; } 

Je lis à partir d’un fichier (que je passe en argument à main, je pense que ce code n’est pas nécessaire ici) que j’appelle la fonction catPrint () avec ce descripteur de fichier et 1 pour le descripteur de sortie afin qu’il imprime à stdout.

Je ne comprends pas pourquoi c’est plus lent parce que j’utilise le même fichier pour tester et avec les deux (le vrai “chat” et le mien), il n’y a qu’un seul read () et un write () pour tout le texte. Le texte entier ne devrait-il pas apparaître à l’écran?

PS: J’ai marqué cela comme un devoir, bien que ma question ici (pourquoi c’est plus lent) ne fait pas partie des devoirs. J’ai seulement eu besoin d’utiliser les appels système pour créer une fonction de type “chat”, ce qui est fait. Je suis juste insortinggué par mon code qui est un peu plus lent.

PROBLEME RESOLU AVEC STUPIDITE DE MOI:
J’ai juste décidé d’appeler le chat original de linux à quelques resockets sur le même fichier, l’un après l’autre, et je me suis rendu compte que c’était aussi lent certaines des fois que je l’ai appelé, aussi lent que le mien. Je suppose que tout va mieux que …

Désolé de perdre votre temps comme ce peuple.

Ah, sur la base de votre édition, vous avez été mordu par le tampon readahead. Vous ne pouvez pas tester deux programmes qui lisent des fichiers côte à côte en les exécutant une fois. Le premier sera toujours plus lent car le fichier est sur le disque, une fois le fichier en mémoire, le second sera plus rapide, vous devrez soit créer de nouvelles données pour chacun, soit en exécuter un pour qu’ils profitent du tampon readahead.

Recherche mmap (2).

Vous allez jeter des aigus de ftell / fread, mais il va ignorer une couche d’indirection si le débit de lecture est vraiment important.

Peut-être avez-vous compilé sans optimisation (ou sans un paramètre d’optimisation aussi élevé)?

De plus, votre code appellera sysWriteBuffer une fois avec readBytes égal à zéro – cela l’explique peut-être (partiellement)?

Vous pouvez également mettre en ligne sysWriteBuffer (via un commutateur de compilation ou à la main).

“inlining” signifie copier le corps d’une fonction sur son site d’appel afin de supprimer la surcharge liée à l’appel d’une fonction. Parfois, les compilateurs le font automatiquement (je pense que -O3 active cette optimisation dans gcc). Vous pouvez également utiliser le mot-clé inline dans gcc pour indiquer au compilateur d’inclure une fonction. Si vous faites cela, votre déclaration ressemblera à ceci:

 static inline int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) { .... 

Sans comparer les codes sources, il est difficile de dire. Si vous comparez votre chat avec GNU cat, souvenez-vous que vous comparez un code de quelques heures / jours à un code qui a évolué depuis plus de vingt ans.

Vous souhaiterez peut-être effectuer une parsing plus complète des performances, en exécutant les deux programmes avec des tailles d’entrée différentes, à partir de différents périphériques (un disque RAM serait utile) et plusieurs fois de suite. Vous devez essayer de déterminer où il est plus lent dans votre programme.

Puisque cat lui-même est vraiment sortingvial (et vous avez dit dans un commentaire que vous optimisiez déjà la compilation), je parie que l’impact que vous observez sur les performances ne se trouve pas dans l’algorithme, mais dans les temps de chargement du programme. Si le fichier binary du système est pré – lié (ce qui est commun sur la plupart des dissortingbutions), vous verrez qu’il est chargé plus rapidement que tous les programmes que vous comstackz vous-même (jusqu’à ce que vous incluiez les liens de vos programmes).

Combien? Le chat canonique est quelque chose comme

 char bufr[BUFSIZ]; ssize_t len; while((len=read(fdin, bufr, BUFSIZ)) >0) write(fdout, bufr, len); 

qui enregistre quelques instructions.

Avez-vous comparé les strace des deux? Vous pouvez essayer d’utiliser le paramètre -tt pour obtenir la synchronisation des appels système.