Eu tenho um arquivo de texto grande (1,5 G),
Quero saber qual é a ferramenta mais rápida e confiável no Linux.
Eu costumo usar:
awk '!x[$0]++' file.txt
Mas quando eu uso o htop
comando, vejo que meu uso de memória está aumentando.
Quero saber qual é a mais rápida e confiável para arquivos enormes.
uniq?
sort?
sed?
awk?
Por quê?
time
?Respostas:
Vamos considerar como cada solução funciona.
uniq
Isso requer que o arquivo já esteja classificado. Caso contrário, você deve canalizá-losort
primeiro, o que significa quesort
é necessário ler o arquivo inteiro na memória, reordená-lo (O(n log n)
) e depois gravá-lo no canal. O trabalho deuniq
é muito barato, uma vez que ele só precisa comparar linhas adjacentes de sua entrada.sort -u
Isso combina o trabalho desort | uniq
. Isso precisa coletar todas as entradas exclusivas na memória, como oawk
script, mas também perde tempo classificando-as antes de produzir a saída. Isto éO(n log n)
, embora neste cason
seja o número de itens exclusivos, nem todas as entradas. Então é melhor que o cachimbo.sed
Não sei por que você listou isso, pois não consigo pensar em uma boa maneira de fazer issosed
. Talvez se você primeiro classificá-lo e canalizar para umsed
script, existe uma maneira de comparar linhas adjacentes. Então,sed
seria apenas fazer o queuniq
faz, euniq
provavelmente faz o mais eficientemente possível.awk
Provavelmente, é o melhor, porque apenas faz a quantidade mínima de trabalho necessária. Ao ler cada linha, ele faz uma pesquisa de hash eficiente para verificar se a linha já está em sua memória e armazena apenas as linhas exclusivas como chaves de hash e um contador como valor. (Se a linha não estava presente anteriormente, a condição será verdadeira, portanto a linha será impressa. Caso contrário, não será.) Isso usaO(n)
tempo eO(uniq n)
memória.Todo método utilizará uma quantidade considerável de memória, para classificar a entrada ou acompanhar quais entradas foram vistas, para que possam remover duplicatas.
fonte
awk
também explica por que usa quantidades crescentes de memória. Qualquer coisa que faça uma classificação acabará fazendo isso também, apenas 1) provavelmente usará tudo de uma vez, 2) poderá usar um pouco mais, dependendo do número de chaves únicas ou duplicadas.sort
recorre a arquivos temporários (de maneira inteligente) para evitar encher a memória. Seu uso de memória é vinculado. O limite é personalizável com algumas implementações de classificação. É mais eficiente permitir que o sistema troque a memória aleatoriamente para o disco (o que também afeta também os aplicativos no sistema).awk
a memória está acabando,sort
talvez seja a única solução, pois foi projetada para lidar com isso. Por outro lado, toda a leitura e gravação em disco reduzirá a velocidade, portanto, provavelmente levará muito tempo para ser concluída. Se você estiver lidando com quantidades tão grandes de dados, provavelmente deverá usar um DBMS em vez de arquivos de texto.O(n log n)
? Ou apenas você conhece isso de outro lugar?Eu descobri que esse tipo parece ser a ferramenta uniq mais rápida, como mostrado aqui -> A maneira mais rápida de excluir duplicatas em uma grande lista de palavras?
fonte
Eu só queria ressaltar que o gnu
uniq
parece terrivelmente lento, mesmo em uma lista classificada.Eu apenas tentei obter uma lista de prefixos de diretório de uma lista de nomes de arquivos classificados:
sort -u parece duas vezes mais rápido que o uniq, e isso ocorre com a leitura de stdin e escrita para stdout, então não vejo ainda nenhuma paralelização. Eu não tenho idéia por que o uniq deve ser muito mais lento que a classificação, já que não precisa classificar a lista ...
A saída desse comando é muito pequena (existem muitas duplicatas), apenas 264kb e a classificação termina instantaneamente após a conclusão do PV.
As mesmas velocidades permanecem se você inverter a ordem dos comandos, meu fluxo é limitado pelo tempo da CPU aqui, não pelo acesso ao disco e caches (eu tenho apenas 8 GB de RAM e minha troca não é usada)
Estou executando isso em uma máquina fedora 31 com gnu coreutils sort e uniq e gnu awk; locale está definido como en_US.UTF-8
ATUALIZAÇÃO , como isso me intrigou bastante, fiz mais alguns testes, vamos cortar a parte do caminho e garantir que o arquivo esteja bem classificado
cat all_files | cut -d '/' -f 1,2,3,4 | sort -T . > test
Isso leva 8,4 minutos. teste agora é 7,9 GB grande
vamos executar essas ferramentas no arquivo em vez de em um pipe, isso permitirá que essas ferramentas otimizem um pouco mais, como a classificação será multithread. e também de um ssd mais rápido.
Você pode não perceber que essa classificação também está consumindo muita memória, pois faz truques inteligentes com arquivos temporários em / tmp, que podem ser tmpfs e estarão em sua memória RAM (tente classificar um arquivo maior que / tmp, você irá correr para o espaço problemas, é por isso que eu preciso da bandeira -T. no comando acima)
Parece que sua solução awk é a mais rápida dessas 3 e, na verdade, usa menos memória
update2 e agora com uma localidade mais simples
Desta vez, o uniq vence a corrida ... como Stéphane Chazelas sugere nos comentários, definir seu local para C torna a classificação e o uniq muito mais rápidos!
fonte
sort
euniq
? Qual local?