Precisa de sugestões de especialistas na comparação abaixo:
Segmento de código usando loop:
for file in `cat large_file_list`
do
gzip -d $file
done
Segmento de código usando expansão simples:
gzip -d `cat large_file_list`
Qual será mais rápido? Tem que manipular um grande conjunto de dados.
linux
bash
shell-script
shell
Leon
fonte
fonte
gzip
o sistema, o número de arquivos na lista de arquivos e o tamanho desses arquivos.xargs gzip -d < large_file_list
, mas cuidado com os espaços em nomes de arquivos, talvez comtr \\n \\0 large_file_list | xargs -0 gzip -d
Respostas:
Complicações
O seguinte funcionará apenas algumas vezes:
Três problemas são (na
bash
maioria das conchas semelhantes a Bourne):Ele falhará se qualquer nome de arquivo tiver uma guia de espaço ou caracteres de nova linha (supondo
$IFS
que não tenha sido modificado). Isso ocorre por causa da divisão da palavra do shell .Também é provável que falhe se algum nome de arquivo tiver caracteres ativos globos nele. Isso ocorre porque o shell aplicará a expansão do nome do caminho à lista de arquivos.
Também falhará se os nomes de arquivos começarem
-
(sePOSIXLY_CORRECT=1
isso se aplicar apenas ao primeiro arquivo) ou se houver algum nome de arquivo-
.Ele também falhará se houver muitos nomes de arquivos nele para caber em uma linha de comando.
O código abaixo está sujeito aos mesmos problemas que o código acima (exceto o quarto)
Solução confiável
Se você
large_file_list
tiver exatamente um nome de arquivo por linha e um arquivo chamado-
não estiver entre eles, e você estiver em um sistema GNU, use:-d'\n'
dizxargs
para tratar cada linha de entrada como um nome de arquivo separado.-r
dizxargs
para não executar o comando se o arquivo de entrada estiver vazio.--
informagzip
que os seguintes argumentos não devem ser tratados como opções, mesmo que iniciem-
.-
sozinho ainda seria tratado como em-
vez do arquivo chamado-
.xargs
colocará muitos nomes de arquivo em cada linha de comando, mas não tantos que exceda o limite da linha de comando. Isso reduz o número de vezes que umgzip
processo deve ser iniciado e, portanto, torna isso rápido. Também é seguro: os nomes dos arquivos também serão protegidos contra a divisão de palavras e a expansão do nome do caminho .fonte
for
loop será, de longe, o mais lento. Os outros dois métodos terão velocidade muito próxima um do outro.xargs
: pelo menos a versão GNU possui a--arg-file
opção (formato abreviado-a
). Então, um poderia fazer em seuxargs -a large_file_list -rd'\n' gzip -d
lugar. Efetivamente, não há diferença, além do fato de que<
é operador de shell e fariaxargs
ler de stdin (que desembolsar "links" para arquivo), enquanto que-a
fariaxargs
explicitamente abrir o arquivo em questãoparallel
para executar várias cópias degzip
, masxargs
(pelo menos a GNU), também tem a-P
opção para isso. Em máquinas multicore, isso pode fazer a diferença. Mas também é possível que a descompressão seja completamente ligada à E / S.Duvido que isso importe muito.
Eu usaria um loop, apenas porque não sei quantos arquivos estão listados no arquivo de lista e (geralmente) não sei se algum dos nomes de arquivos tem espaços em seus nomes. Fazer uma substituição de comando que geraria uma lista muito longa de argumentos pode resultar em um erro "Lista de argumentos muito longa" quando o comprimento da lista gerada for muito longo.
Meu loop ficaria assim
Isso também me permitiria inserir comandos para processar os dados após o
gunzip
comando. De fato, dependendo do que os dados realmente são e do que precisa ser feito com eles, pode até ser possível processá-los sem salvá-los no arquivo:(onde
process_data
está um pipeline que lê os dados não compactados da entrada padrão)Se o processamento dos dados demorar mais que a descompactação, a questão de saber se um loop é mais eficiente ou não se torna irrelevante.
Idealmente , eu preferiria não elaborar uma lista de nomes de arquivos e usar um padrão globbing de nome de arquivo, como em
onde
./*.gz
está algum padrão que corresponde aos arquivos relevantes. Dessa forma, não dependemos do número de arquivos nem dos caracteres usados nos nomes de arquivos (eles podem conter novas linhas ou outros caracteres de espaço em branco, ou começar com traços, etc.)Relacionado:
fonte
Desses, o arquivo com todos os arquivos passados para uma única chamada
gzip
provavelmente será mais rápido, exatamente porque você só precisa iniciargzip
uma vez. (Ou seja, se o comando funcionar, consulte as outras respostas para as advertências.)Mas, gostaria de lembrar a regra de ouro da otimização : não faça isso prematuramente.
Não otimize esse tipo de coisa antes de perceber que é um problema.
Essa parte do programa leva muito tempo? Bem, descomprimir arquivos grandes pode, e você precisará fazê-lo de qualquer maneira, portanto, pode não ser tão fácil de responder.
A medida. Realmente, é a melhor maneira de ter certeza.
Você verá os resultados com seus próprios olhos (ou com seu próprio cronômetro), e eles se aplicarão à sua situação que respostas aleatórias na Internet podem não ter. Coloque as duas variantes nos scripts e execute
time script1.sh
etime script2.sh
. (Faça isso com uma lista de arquivos compactados vazios para medir a quantidade absoluta da sobrecarga.)fonte
Qual a velocidade do seu disco?
Isso deve usar todas as suas CPUs:
Portanto, seu limite provavelmente será a velocidade do seu disco.
Você pode tentar ajustar com
-j
:Isso executará metade dos trabalhos em paralelo como o comando anterior e estressará menos o disco, portanto, dependendo do disco, isso pode ser mais rápido.
fonte