Pourquoi l'utilitaire wc est-il si lent?
Lorsque je l'exécute sur un fichier volumineux, cela prend environ 20 fois plus longtemps que md5sum:
MyDesktop:/tmp$ dd if=/dev/zero bs=1024k count=1024 of=/tmp/bigfile
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.687094 s, 1.6 GB/s
MyDesktop:/tmp$ time wc /tmp/bigfile
0 0 1073741824 /tmp/bigfile
real 0m45.969s
user 0m45.424s
sys 0m0.424s
MyDesktop:/tmp$ time md5sum /tmp/bigfile
cd573cfaace07e7949bc0c46028904ff /tmp/bigfile
real 0m2.520s
user 0m2.196s
sys 0m0.316s
Ce n'est pas seulement une condition de bord étrange causée par le fichier plein de valeurs nulles, je vois la même différence de performances même si le fichier est rempli de données aléatoires ou est un fichier texte.
(c'est sur Ubuntu 13.04, 64 bits)
performance
wc
Johnny
la source
la source
Réponses:
Je suis donc allé à la source, et il semble que la lenteur réside dans la gestion des caractères à deux octets. Essentiellement, pour chaque caractère lu, il doit appeler
mbrtowc()
pour essayer de le convertir en caractère large, puis ce caractère large est testé pour voir s'il s'agit d'un séparateur de mots, d'un séparateur de lignes, etc.En effet, si je change ma
LANG
variable locale par défauten_US.UTF-8
(UTF-8 est un jeu de caractères multi-octets) et que je la mets à "C
" (jeu de caractères simple à un octet), je peuxwc
utiliser des optimisations à un octet, ce qui l'accélère considérablement, en prenant seulement environ un quart aussi longtemps qu'avant.De plus, il n'a qu'à vérifier chaque caractère s'il compte les mots (
-w
), la longueur de ligne (-L
) ou le caractère (-m
). S'il ne fait que compter les octets et / ou les lignes, il peut ignorer la gestion des caractères larges, puis il s'exécute extrêmement rapidement - plus rapidement quemd5sum
.Je l' ai couru à travers
gprof
, et les fonctions qui sont utilisées pour gérer les caractères multi - octets (mymbsinit()
,mymbrtowc()
,myiswprint()
, etc.) prenez environ 30% du temps d'exécution seul, et le code qui étapes à travers la mémoire tampon est beaucoup plus complexe parce qu'il doit gérer les étapes de taille variable dans le tampon pour les caractères de taille variable, ainsi que rembourrer tous les caractères partiellement complétés qui s'étendent sur le tampon jusqu'au début du tampon afin qu'il puisse être géré la prochaine fois.Maintenant que je sais quoi chercher, j'ai trouvé quelques articles mentionnant la lenteur de l'utf-8 avec certains utilitaires:
/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up http://dtrace.org/blogs/brendan/2011/12/08 / 2000x-performance-win /
la source
md5sum
ne vous permettra jamais de compter le nombre de mots etwc
ne calculera pas le hachage md5 du fichier! C'est comme demander pourquoi ma voiture est si lente par rapport à ma machine à écrire lors de l'écriture de texte.wc
fait est liée au CPU, lors du traitement de caractères multi-octets.Juste une supposition, mais vous comparez en quelque sorte les pommes aux oranges en ce qui concerne ce qui
wc
fait vs ce quimd5sum
est en train de faire.La tâche de md5sum
Lorsque
md5sum
traite un fichier, il ouvre simplement le fichier en tant que flux, puis commence à exécuter le flux via la fonction de somme de contrôle MD5 qui nécessite très peu de mémoire. Il est essentiellement lié aux E / S du processeur et du disque.tâche de wc
Lorsqu'il
wc
s'exécute, il en fait beaucoup plus que d'analyser le fichier un caractère à la fois. Il doit en fait analyser la structure du fichier, les lignes à la fois déterminant où se trouvent les limites entre les caractères et s'il s'agit d'une limite de mot ou non.Exemple
Pensez aux chaînes suivantes et à la façon dont chacun des algorithmes devrait les parcourir lors de leur analyse:
Pour MD5, il se déplace trivialement à travers ces chaînes un caractère à la fois. Car
wc
il doit décider ce qu'est une limite de mots et de lignes et garder une trace du nombre d'occurrences qu'il voit.Discussions supplémentaires sur les WC
J'ai trouvé ce défi de codage de 2006 qui traite de la mise
wc
en œuvre dans .NET. Les difficultés sont assez évidentes lorsque vous examinez une partie du pseudo-code, cela pourrait donc aider à faire la lumière sur les raisons pour lesquelles ilwc
semble être beaucoup plus lent que d'autres opérations.la source
wc
compte plusieurs choses lors de l'analyse du fichier. Il compte le nombre de mots, de lignes et d'octets lors de l'analyse du fichier. Lisez la page de manuel!wc
de ne compter que les lignes limite son analyse interne afin qu'il ne compte que ces choses ou ne signale que les résultats des lignes, même s'il comptait toujours tout.