Quindi sono andato alla fonte e sembra che la lentezza sia nella gestione dei caratteri a doppio byte. In sostanza, per ogni personaggio letto, deve chiamare mbrtowc()
per provare a convertirlo in un carattere largo, quindi quel carattere largo viene testato per vedere se è un separatore di parole, un separatore di linea, ecc.
In effetti, se cambio la mia LANG
variabile locale da quella predefinita en_US.UTF-8
(UTF-8 è un set di caratteri multibyte) e la imposto su " C
" (semplice set di caratteri a byte singolo), wc
è in grado di utilizzare le ottimizzazioni a byte singolo, che accelera notevolmente, impiegando solo un quarto di tempo rispetto a prima.
Inoltre, deve controllare ogni carattere solo se sta contando word ( -w
), line length ( -L
) o character ( -m
). Se sta eseguendo solo conteggi di byte e / o righe, può saltare l'ampia gestione dei caratteri e quindi funziona in modo estremamente rapido, più veloce di md5sum
.
Ho eseguito attraverso gprof
, e le funzioni che vengono utilizzati per gestire i caratteri multibyte ( mymbsinit()
, mymbrtowc()
, myiswprint()
, ecc) che occupano circa il 30% del tempo di esecuzione da solo, e il codice che passi attraverso il buffer è molto più complessa perché deve gestire passaggi di dimensioni variabili attraverso il buffer per caratteri di dimensioni variabili, nonché riempire eventuali caratteri parzialmente completati che coprono il buffer all'inizio del buffer in modo che possa essere gestito la volta successiva.
Ora che so cosa cercare, ho trovato alcuni post che menzionano la lentezza utf-8 con alcune utilità:
/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up
http://dtrace.org/blogs/brendan/2011/12/08 / 2000x-prestazioni-win /