Preciso fazer alguns testes de velocidade nos meus comandos do Linux. Os dados de entrada são uma lista de palavras. Por exemplo:
$ cat list
elephant
horse
raven
cat
dog
fish
Para um teste de velocidade razoável, preciso de um arquivo muito maior. Qual é a maneira mais rápida de repetir a lista acima centenas de milhares de vezes?
jot
é uma ferramenta geralmente encontrada por padrão em sistemas BSD (incluindo macOS), mas também pode ser instalada na maioria dos sistemas Linux. O pacote no Ubuntu, por exemplo, é chamadoathena-jot
.Com algumas
head
implementações:Daria a você 1 GiB do conteúdo
list
repetido indefinidamente.Com ksh/zsh/bash, você pode substituir
"$(cat list)"
por"$(<list)"
.-c
não é uma opção padrão dehead
e nem todas as implementações que o suportam suportam esses sufixos KMGTPE.... Observe também que provavelmente cortará uma linha no meio e a deixará sem limite.Imprimir o valor
1000000
das linhas seria padrão e portátil.Aqui está uma maneira, usando perl:
A
-g
flag dizperl
para ler o arquivo inteiro de uma vez e executar o script fornecido-e
nele. O script em si usa apenas a sintaxe perl especial<>
que representa a entrada padrão e então imprimimos@list
vezes 10. Na sua entrada,x 3
para simplificar, isso fornece:Então, se você quiser milhares, basta fazer algo como
No meu sistema, isso cria um arquivo de 3,2G em menos de 5 segundos:
Duplique repetidamente. Este código é eficiente porque faz um loop apenas no log 2 n vezes para aumentar o tamanho do arquivo por um fator de n . (1 iteração para o dobro do tamanho, 2 iterações para quatro vezes o tamanho, etc.)
Isto lhe dará um fator de multiplicação de 131072 (2 17 ), que corresponde à sua necessidade de " repetir a lista acima centenas de milhares de vezes ".
Você poderia usar
cat a a a a
para aumentar em 4 9 , alcançando um fator de multiplicação de 262144 com 9 iterações.A
{1..17}
construção é uma expansão de chaves suportada por shells menos minimalistas, comoksh
,bash
,zsh
(mas nãodash
ou POSIX)Como você não se importa com os números repetidos, você pode combinar os comandos “timeout” e “yes” para criar repetições enormes muito rapidamente. Por exemplo:
Altere o argumento de tempo de 0,01 segundos para atender às suas necessidades. Mantenha-o baixo, pois mesmo com 1s você pode acabar com 50 milhões de linhas!
Basta usar um loop for:
Isso basicamente anexa o conteúdo inicial dos
n
tempos da lista fornecida ao mesmo arquivo. Ajustelimit
efile
faça funcionar da maneira que você deseja.Se o conteúdo real da lista não for importante, você poderia fazer algo mais flexível e apenas anexar uma string arbitrária a um arquivo, assim:
Ou diretamente da linha de comando usando uma sintaxe mais concisa:
Editar: Obrigado a @muru pela sugestão. É claro que fazer um redirecionamento em cada iteração não é eficiente, anexar o conteúdo gerado logo após o loop for é muito melhor e mais rápido. Atualizei a resposta de acordo.
Atualizar
Se a eficiência for uma preocupação e uma solução mais escalável for necessária, você pode usar os comandos externos
seq
eshuf
gerar uma lista aleatória do tamanho que você precisa:Para ver a diferença com mais clareza, vamos aumentar o número de iterações para 1.000.000 e medir o tempo:
Isso é quase 40 vezes mais rápido do que executar o loop for com
$RANDOM
, que levou 5,935s na minha máquina com o mesmolimit
.