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 largo, então esse caractere largo é testado para ver se é um separador de palavras, um separador de linhas, etc.
De fato, se eu alterar minha variável de local LANG
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 único), wc
é capaz de usar otimizações de byte único, o que acelera consideravelmente, levando apenas cerca de um quarto do tempo anterior.
Além disso, ele só precisa verificar se cada caractere está em andamento ( -w
), o comprimento da linha ( -L
) ou o caractere ( -m
) conta. Se estiver apenas fazendo contagem de bytes e / ou linhas, ele pode ignorar o tratamento de caracteres amplo e, em seguida, é executado com extrema rapidez - mais rápido do que md5sum
.
Eu o executei através de gprof
, e as funções que são usadas para manipular os caracteres multibyte ( mymbsinit()
, mymbrtowc()
, myiswprint()
, etc) estão ocupando cerca de 30% do tempo de execução sozinho, e o código que percorre o buffer é muito mais complexo porque ele tem que manipular etapas de tamanhos variáveis através do buffer para caracteres de tamanho variável, bem como preencher quaisquer caracteres parcialmente completos que abranjam o buffer de volta ao início do buffer para que ele possa ser tratou da próxima vez.
Agora que sei o que procurar, encontrei alguns posts mencionando a lentidão do utf-8 com alguns utilitários: