Pour un très gros fichier comme 1 Go, wc -l
il s'avère être lent. Avons-nous un moyen plus rapide de calculer le nombre de sauts de ligne pour un fichier particulier?
command-line
wc
prosti
la source
la source
0x0A
iness, les E / S sont sans aucun doute le goulot d'étranglement.wc
avoir trop de frais généraux, vous pouvez essayer d'implémenter le vôtreforeach byte in file: if byte == '\n': linecount++
. S'il est implémenté en C ou en assembleur, je ne pense pas que cela va être plus rapide, sauf peut-être dans l'espace du noyau sur un RTOS avec la plus haute priorité (ou même utiliser une interruption pour cela - vous ne pouvez tout simplement rien faire d'autre avec le système. .. d'accord, je m'égare ;-))time wc -l some_movie.avi
sur un fichier non mis en cache, ce qui a entraîné5172672 some_movie.avi -- real 0m57.768s -- user 0m0.255s -- sys 0m0.863s
. Ce qui prouve que @thrig a raison, les E / S anéantissent vos performances dans ce cas.time wc -l some_large_file_smaller_than_cache
deux fois de suite rapidement et de voir à quelle vitesse la deuxième opération est, puis detime wc -l some_large_file_larger_than_cache
voir comment le temps ne change pas entre les exécutions. Pour un fichier de ~ 280 Mo ici, le temps passe de 1,7 seconde à 0,2 seconde, mais pour un fichier de 2 Go, c'est 14 secondes les deux fois./usr/bin/time wc -l <file>
dit-on, quel est votre matériel? Est-ce plus rapide si vous exécutez la commande à plusieurs reprises? Nous avons vraiment besoin de plus d'informations;)Réponses:
Vous pouvez essayer d' écrire en C:
Enregistrer par exemple,
wcl.c
compiler par exemple avecgcc wcl.c -O2 -o wcl
et exécuter avecCela trouve des sauts de ligne saupoudrés dans un fichier de 1 Go sur mon système en environ 370 ms ( cycles répétés). (L'augmentation de la taille des tampons augmente légèrement le temps, ce qui est normal - BUFSIZ devrait être presque optimal). C'est très comparable aux ~ 380 ms dont je viens
wc -l
.Mmaping me donne un meilleur temps d'environ 280 ms , mais il a bien sûr la limitation d'être limité aux fichiers réels (pas de FIFOS, pas d'entrée de terminal, etc.):
J'ai créé mon fichier de test avec:
et ajouté quelques nouvelles lignes de test avec:
et un éditeur hexadécimal.
la source
for
boucle OpenMP ) afin que certains progrès puissent être réalisés pendant qu'un thread est bloqué en attente d'entrée. Mais d'un autre côté, cela peut entraver la planification des E / S, donc tout ce que je peux recommander est de l'essayer et de mesurer!read()
version peut bénéficier d'une lecture anticipée.Vous pouvez améliorer la solution proposée par @pskocik en réduisant le nombre d'appels vers
read
. Il y a beaucoup d'appels pour lire desBUFSIZ
morceaux à partir d'un fichier 1 Go. L'approche habituelle consiste à augmenter la taille du tampon:BUFSIZ
c'est 8192. Avec le programme d'origine, c'est 120 000 opérations de lecture. Vous pouvez probablement vous permettre un tampon d'entrée de 1 Mo pour le réduire d'un facteur 100.Lors de l'analyse comparative des différentes approches, vous pouvez garder à l'esprit que certains systèmes (tels que Linux) utilisent la plupart de la mémoire inutilisée de votre machine comme cache disque. Il y a quelque temps (il y a près de 20 ans, mentionné dans la vile FAQ ), j'étais perplexe devant les bons résultats inattendus d'un algorithme de pagination (pas très bon) que j'avais développé pour gérer les conditions de faible mémoire dans un éditeur de texte. On m'a expliqué qu'il fonctionnait rapidement parce que le programme fonctionnait à partir des tampons de mémoire utilisés pour lire le fichier, et que seulement si le fichier était relu ou écrit, il y aurait une différence de vitesse.
La même chose s'applique à
mmap
(dans un autre cas toujours sur ma liste de tâches à intégrer dans une FAQ, un développeur a rapporté de très bons résultats dans un scénario où le cache disque était la raison réelle de l'amélioration). L'élaboration de repères nécessite du temps et du soin pour analyser les raisons de la bonne (ou mauvaise) performance.Lectures complémentaires:
la source
dd
, en utilisant des tampons de 1 Mo sont plus lents que 8 Ko . La valeur par défaut de 8 Ko pour wc est en fait assez bien choisie, elle sera presque optimale pour une large gamme de systèmes.