Então eu fui para a fonte e parece que a lentidão está no tratamento de caracteres de byte duplo. Essencialmente, para cada caractere lido, ele precisa chamar mbrtowc()
para tentar convertê-lo em um caractere amplo, e esse caractere amplo é testado para verificar se é um separador de palavras, separador de linhas, etc.
De fato, se eu alterar minha LANG
variável de localidade do padrão en_US.UTF-8
(UTF-8 é um conjunto de caracteres multibyte) e defini-la como " C
" (conjunto de caracteres simples de byte simples), wc
será possível usar otimizações de byte único, o que acelera consideravelmente, levando apenas cerca de um quarto do tempo antes.
Além disso, ele só precisa verificar cada caractere se estiver executando palavras ( -w
), comprimento de linha ( -L
) ou caracteres ( -m
). Se estiver executando apenas contagens de bytes e / ou linhas, pode ignorar o amplo manuseio de caracteres e executar extremamente rápido - mais rapidamente que md5sum
.
Corri-lo através de gprof
, e as funções que são utilizados para tratar os caracteres de vários bytes ( mymbsinit()
, mymbrtowc()
, myiswprint()
, etc) estão ocupando cerca de 30% do tempo de execução sozinho, e o código que os passos através do tampão é muito mais complexo porque tem que lida com etapas de tamanho variável através do buffer para caracteres de tamanho variável, além de preencher caracteres parcialmente concluídos que abrangem o buffer até o início do buffer, para que ele possa ser tratado na próxima vez.
Agora que sei o que procurar, encontrei alguns posts mencionando a lentidão do utf-8 em alguns utilitários:
/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up
http://dtrace.org/blogs/brendan/2011/12/08 / 2000x-performance-win /