Minha sugestão seria hexdump
. Ele exibe o conteúdo de qualquer arquivo ou dispositivo em formato hexadecimal como linhas de 16 bytes, mas se duas linhas subsequenciais forem iguais, elas serão omitidas.
Aqui está um exemplo de saída do arquivo de 512 MB virtualdevice
, que é preenchido com zeros apenas no diretório atual do meu disco rígido. A coluna mais à esquerda é o deslocamento da linha na notação hexadecimal, as 8 colunas seguintes são os dados reais, agrupados em dois bytes (4 caracteres hexadecimais):
$ hexdump ./virtualdevice
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
20000000
Desempenho:
Eu fiz o esforço e comparei a minha solução com as outras por tempo de execução real e tempo de CPU para o arquivo de exemplo descrito (512 MB, contendo apenas zeros binários, localizados no HDD).
Eu medi todas as soluções com o comando time
duas vezes com o cache de disco recém-limpo e duas vezes com o arquivo já em cache. Os nomes de hora são iguais aos do comando time
, e a linha adicional CPU
é apenas a soma do USER
+ SYS
times. Pode exceder o REAL
tempo porque estou executando uma máquina dual-core.
Para a maioria das pessoas, os números interessantes são REAL
(tempo do início ao fim, como se medido com um cronômetro. Isso também contém espera e tempo de CPU de outros processos) e CPU
(tempo de CPU que é realmente ocupado pelo comando).
Resumo:
O melhor desempenho tem a segunda versão otimizada do muru ( grep -zq . DEVICE
) que usa incrivelmente o tempo de processamento da CPU.
Rank 2 share cmp /dev/zero DEVICE
( kos 'solução otimizada) e minha própria solução hexdump DEVICE
. Não há quase nenhuma diferença entre eles.
Para canalizar os dados de dd
para cmp
( dd if=/dev/zero | cmp - DEVICE
- kos 'solução não otimizada) é muito ineficiente, a tubulação parece consumir muito tempo de processamento.
Usar dd
e grep
mostra o pior desempenho dos comandos testados.
Conclusão:
Embora a parte mais crítica de operações como estas seja o tempo de acesso do IO, existem diferenças significativas na velocidade de processamento e eficiência das abordagens testadas.
Se você for muito impaciente, use a segunda versão da resposta do muru ( grep -zq . DEVICE
)!
Mas você também pode usar a segunda versão da resposta kos '( cmp /dev/zero DEVICE
) ou a minha própria ( hexdump device
), pois elas têm um desempenho quase tão bom.
No entanto, minha abordagem tem a vantagem de você ver imediatamente o conteúdo do arquivo e pode aproximar quantos bytes diferem de zero e onde eles estão localizados. Se você tiver muitos dados alternados, a saída aumentará e provavelmente diminuirá a velocidade.
O que você deve evitar em qualquer caso é usar dd
e pipes. O desempenho de dd
provavelmente poderia ser melhorado definindo um tamanho de buffer adequado, mas por que fazê-lo da maneira mais complicada?
Por favor, note também que o teste foi feito em um arquivo no meu disco em vez de um dispositivo real. Além disso, o arquivo continha apenas zeros. Ambos afetam as performances.
Aqui estão os resultados detalhados:
-
hexdump ./virtualdevice
(minha própria solução):
| Uncached: | Cached:
Time: | Run 1: Run 2: | Run 1: Run 2:
--------+-------------------+------------------
REAL | 7.689s 8.668s | 1.868s 1.930s
USER | 1.816s 1.720s | 1.572s 1.696s
SYS | 0.408s 0.504s | 0.276s 0.220s
CPU | 2.224s 2.224s | 1.848s 1.916s
-
dd if=./virtualdevice | grep -zq . && echo non zero
(solução não otimizada de muru ):
| Uncached: | Cached:
Time: | Run 1: Run 2: | Run 1: Run 2:
--------+-------------------+------------------
REAL | 9.434s 11.004s | 8.802s 9.266s
USER | 2.264s 2.364s | 2.480s 2.528s
SYS | 12.876s 12.972s | 12.676s 13.300s
CPU | 15.140s 15.336s | 15.156s 15.828s
-
grep -zq . ./virtualdevice && echo non zero
(a solução otimizada do muru ):
| Uncached: | Cached:
Time: | Run 1: Run 2: | Run 1: Run 2:
--------+-------------------+------------------
REAL | 8.763s 6.485s | 0.770s 0.833s
USER | 0.644s 0.612s | 0.528s 0.544s
SYS | 0.440s 0.476s | 0.236s 0.264s
CPU | 1.084s 1.088s | 0.764s 0.808s
-
Solução
dd if=/dev/zero | cmp - ./virtualdevice
( kos 'não otimizada):
| Uncached: | Cached:
Time: | Run 1: Run 2: | Run 1: Run 2:
--------+-------------------+------------------
REAL | 7.678s 6.539s | 3.151s 3.147s
USER | 2.348s 2.228s | 2.164s 2.324s
SYS | 3.672s 3.852s | 3.792s 3.516s
CPU | 6.020s 6.080s | 5.956s 5.840s
-
cmp /dev/zero ./virtualdevice
(solução kos otimizada):
| Uncached: | Cached:
Time: | Run 1: Run 2: | Run 1: Run 2:
--------+-------------------+------------------
REAL | 6.340s 9.183s | 1.660s 1.660s
USER | 1.356s 1.384s | 1.216s 1.288s
SYS | 0.640s 0.596s | 0.428s 0.360s
CPU | 1.996s 1.980s | 1.644s 1.648s
Comandos usados:
Para os quatro testes, executei o seguinte procedimento duas vezes para reduzir as imprecisões, substituindo <COMMAND>
pelo comando exato do título de cada tabela.
-
Deixe o kernel soltar todos os caches de disco:
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
-
Primeira execução cronometrada (sem cache), o arquivo é carregado no cache durante o seguinte:
time <COMMAND>
-
Segunda execução cronometrada (em cache). Desta vez, a maioria dos dados é retirada do cache de disco da RAM, portanto, é muito mais rápida do que ao acessar o disco diretamente:
time <COMMAND>