Por que o utilitário wc é tão lento?
Quando o executo em um arquivo grande, leva cerca de 20 vezes mais que o 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
Não é apenas uma condição de borda estranha causada pelo fato de o arquivo estar cheio de nulos, vejo a mesma diferença de desempenho, mesmo que o arquivo seja preenchido com dados aleatórios ou seja um arquivo de texto.
(isso é no Ubuntu 13.04, 64 bits)
performance
wc
Johnny
fonte
fonte
Respostas:
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ãoen_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 quemd5sum
.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 /
fonte
md5sum
nunca permitirá que você conte o número da palavra ewc
não computará o hash md5 do arquivo! É como perguntar por que meu carro é tão lento em comparação com a minha máquina de escrever ao escrever um texto.wc
, de fato, está vinculada à CPU ao processar caracteres de vários bytes.Apenas um palpite, mas você está comparando maçãs com laranjas em relação ao que
wc
está fazendo versus o quemd5sum
está fazendo.Tarefa de md5sum
Quando
md5sum
processa um arquivo, ele simplesmente abre o arquivo como um fluxo e começa a executá-lo através da função de soma de verificação MD5, que precisa de muito pouca memória. Essencialmente, CPU e disco ligado a E / S.tarefa de wc
Quando
wc
executado, ele está fazendo muito mais do que apenas analisar o arquivo, um caractere de cada vez. Ele precisa realmente analisar a estrutura do arquivo, linhas de cada vez, fazendo determinações sobre onde estão os limites entre os caracteres e se é um limite de palavra ou não.Exemplo
Pense nas seguintes seqüências de caracteres e como cada um dos algoritmos teria que passar por elas enquanto as analisava:
Para o MD5, ele move trivialmente essas strings, um caractere por vez. Pois
wc
ele tem que decidir o que é um limite de palavras e linhas e acompanhar o número de ocorrências que vê.Discussões adicionais do wc
Eu encontrei esse desafio de codificação de 2006 que discute a implementação
wc
no .NET. As dificuldades são bastante óbvias quando você olha para alguns dos pseudo-códigos, portanto, isso pode ajudar a começar a esclarecer por quewc
parece ser muito mais lento que outras operações.fonte
wc
conta várias coisas enquanto analisa o arquivo. Conta o número de palavras, linhas e bytes à medida que analisa o arquivo. Leia a página de manual!wc
apenas para contar linhas limita a análise interna, para que apenas conte essas coisas ou apenas relate os resultados das linhas, mesmo que ainda conte tudo.