A opção "bs" em "dd" realmente melhora a velocidade?

58

De vez em quando, me dizem que, para aumentar a velocidade de um "dd", devo escolher cuidadosamente um "tamanho de bloco" adequado.

Mesmo aqui, no ServerFault, alguém escreveu que " ... o tamanho ideal do bloco depende do hardware ... " (iain) ou " ... o tamanho perfeito dependerá do barramento do sistema, controlador do disco rígido, unidade específica e os drivers para cada um desses ... " (chris-s)

Como meu sentimento era um pouco diferente ( BTW: eu pensei que o tempo necessário para ajustar profundamente o parâmetro bs era muito maior que o ganho recebido, em termos de economia de tempo e que o padrão era razoável ), hoje eu apenas fui através de alguns benchmarks rápidos e sujos.

Para diminuir as influências externas, decidi ler:

  • de um cartão MMC externo
  • de uma partição interna

e:

  • com sistemas de arquivos relacionados desmontados
  • enviando a saída para / dev / null para evitar problemas relacionados à "velocidade de gravação";
  • evitando alguns problemas básicos do armazenamento em cache do HDD, pelo menos ao envolver o HDD.

Na tabela a seguir, relatei minhas descobertas, lendo 1 GB de dados com valores diferentes de "bs" ( você pode encontrar os números brutos no final desta mensagem ):

insira a descrição da imagem aqui

Basicamente, ressalta que:

  • MMC: com um bs = 4 (sim! 4 bytes), atingi uma taxa de transferência de 12MB / s. A valores não tão distantes atingiram o máximo de 14,2 / 14,3 que obtive de bs = 5 e acima;

  • HDD: com um bs = 10 atingi 30 MB / s. Certamente menor que os 95,3 MB obtidos com o padrão bs = 512, mas ... significativo também.

Além disso, ficou muito claro que o tempo de sistema da CPU era inversamente proporcional ao valor de bs (mas isso parece razoável, pois quanto menor o bs, maior o número de chamadas de sistema geradas pelo dd).

Dito isso, agora a pergunta: alguém pode explicar (um hacker de kernel?) Quais são os principais componentes / sistemas envolvidos em tal taxa de transferência e se vale realmente a pena especificar um bs superior ao padrão?


Caso MMC - números brutos

bs = 1 milhão

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1M count=1000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 74,1239 s, 14,1 MB/s

real    1m14.126s
user    0m0.008s
sys     0m1.588s

bs = 1k

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1k count=1000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,7795 s, 14,1 MB/s

real    1m12.782s
user    0m0.244s
sys     0m2.092s

bs = 512

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=512 count=2000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 72,867 s, 14,1 MB/s

real    1m12.869s
user    0m0.324s
sys     0m2.620s

bs = 10

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,1662 s, 14,3 MB/s

real    1m10.169s
user    0m6.272s
sys     0m28.712s

bs = 5

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 70,415 s, 14,2 MB/s

real    1m10.417s
user    0m11.604s
sys     0m55.984s

bs = 4

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 80,9114 s, 12,4 MB/s

real    1m20.914s
user    0m14.436s
sys     1m6.236s

bs = 2

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 161,974 s, 6,2 MB/s

real    2m41.976s
user    0m28.220s
sys     2m13.292s

bs = 1

root@iMac-Chiara:/tmp# time dd if=/dev/sdc of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 325,316 s, 3,1 MB/s

real    5m25.318s
user    0m56.212s
sys     4m28.176s

Caso do disco rígido - números brutos

bs = 1

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1 count=1000000000
1000000000+0 record dentro
1000000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 341,461 s, 2,9 MB/s

real    5m41.463s
user    0m56.000s
sys 4m44.340s

bs = 2

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=2 count=500000000
500000000+0 record dentro
500000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 164,072 s, 6,1 MB/s

real    2m44.074s
user    0m28.584s
sys 2m14.628s

bs = 4

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=4 count=250000000
250000000+0 record dentro
250000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 81,471 s, 12,3 MB/s

real    1m21.473s
user    0m14.824s
sys 1m6.416s

bs = 5

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=5 count=200000000
200000000+0 record dentro
200000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 66,0327 s, 15,1 MB/s

real    1m6.035s
user    0m11.176s
sys 0m54.668s

bs = 10

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=10 count=100000000
100000000+0 record dentro
100000000+0 record fuori
1000000000 byte (1,0 GB) copiati, 33,4151 s, 29,9 MB/s

real    0m33.417s
user    0m5.692s
sys 0m27.624s

bs = 512 (compensando a leitura, para evitar cache)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=512 count=2000000 skip=6000000
2000000+0 record dentro
2000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,7437 s, 95,3 MB/s

real    0m10.746s
user    0m0.360s
sys 0m2.428s

bs = 1k (compensando a leitura, para evitar armazenamento em cache)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1k count=1000000 skip=6000000
1000000+0 record dentro
1000000+0 record fuori
1024000000 byte (1,0 GB) copiati, 10,6561 s, 96,1 MB/s

real    0m10.658s
user    0m0.164s
sys 0m1.772s

bs = 1k (compensando a leitura, para evitar armazenamento em cache)

root@iMac-Chiara:/tmp# time dd if=/dev/sda3 of=/dev/null bs=1M count=1000 skip=7000
1000+0 record dentro
1000+0 record fuori
1048576000 byte (1,0 GB) copiati, 10,7391 s, 97,6 MB/s

real    0m10.792s
user    0m0.008s
sys 0m1.144s
Damiano Verzulli
fonte
11
O que seria realmente bom é ter um bs=autorecurso ddque detecte e use o parâmetro bs ideal do dispositivo.
4
O que seria extremamente bom é um gráfico de vários bstamanhos plotados em relação à velocidade, em vez de 15 dúzias de blocos de código em uma única pergunta. Exigiria menos espaço e seria infinitamente mais rápido de ler. Uma imagem realmente é vale thoursand palavras.
precisa saber é o seguinte
2
@ BigHomie - Pensei em fornecer um gráfico, mas ... existem vários problemas de "dimensionamento". Seria necessário, provavelmente, uma escala logarítmica nos dois eixos e ... enquanto pensava nisso, pensei que não era um problema fácil (e rápido) de resolver. Então, mudei para a versão "table". Quanto aos "... 15 dúzias de blocos de código", eu queria que todos tivessem a chance de verificar "números brutos", para evitar qualquer interferência (pessoal, minha).
Damiano Verzulli
11
@DamianoVerzulli, a mesa é legal, por favor, ignore meu discurso retórico, eu lhe dei um voto positivo por provar nossas superstições de qualquer maneira, e eu sei em primeira mão que mexer no tamanho do byte alterará a velocidade, eu também poderia responder.
precisa saber é o seguinte
11
@warren - para obter 4G você também pode fazer bs=8k count=512Kou bs=1M count=4Knão me lembro de potências de 2 passado 65536
user313114

Respostas:

24

O que você fez é apenas um teste de velocidade de leitura. se, na verdade, você está copiando blocos para outro dispositivo, há uma pausa na leitura enquanto o outro dispositivo aceita os dados que deseja gravar; quando isso acontece, você pode encontrar problemas de latência rotacional no dispositivo de leitura (se for um disco rígido) e, portanto, geralmente é muito mais rápido ler trechos de 1 milhão de disco rígido à medida que você enfrenta a latência rotacional com menos frequência.

Sei que, quando copio discos rígidos, obtenho uma taxa mais rápida especificando do bs=1Mque usando bs=4kou o padrão. Estou falando de melhorias na velocidade de 30 a 300%. Não há necessidade de ajustá-lo para o melhor absoluto, a menos que seja tudo o que você faz todos os dias. mas escolher algo melhor que o padrão pode reduzir horas do tempo de execução.

Quando você o usa de verdade, tente alguns números diferentes e envie ddum SIGUSR1sinal ao processo para que ele emita um relatório de status para que você possa ver como está indo.

✗ killall -SIGUSR1 dd
1811+1 records in
1811+1 records out
1899528192 bytes (1.9 GB, 1.8 GiB) copied, 468.633 s, 4.1 MB/s
user313114
fonte
2014 Macbook Pro Retina copiando para USB3 avaliado em 90 MB / s de gravação: $ sudo dd if=~/Downloads/Qubes-R4.0-rc4-x86_64.iso of=/dev/rdisk2 status=progressshows 6140928 bytes (6.1 MB, 5.9 MiB) copied, 23 s, 267 kB/s. Eu cancelei isso porque estava demorando muito. Agora especificando o tamanho do bytes: $ sudo dd if=~/Downloads/Qubes-R4.0-rc4-x86_64.iso of=/dev/rdisk2 bs=1M status=progressshows4558159872 bytes (4.6 GB, 4.2 GiB) copied, 54 s, 84.4 MB/s
Eric Duncan
9

No que diz respeito ao disco rígido interno, pelo menos - quando você está lendo no dispositivo, a camada de bloco precisa pelo menos recuperar um setor com 512 bytes.

Portanto, ao manipular uma leitura de 1 byte, você realmente só leu a partir do disco na recuperação de bytes alinhados pelo setor. As 511 vezes restantes são servidas por cache.

Você pode provar isso da seguinte maneira: neste exemplo sdbestá um disco de interesse:

# grep sdb /proc/diskstats
8      16 sdb 767 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...
# dd if=/dev/sdb of=/dev/null bs=1 count=512
512+0 records in
512+0 records out
512 bytes (512 B) copied, 0.0371715 s, 13.8 kB/s
# grep sedb /proc/diskstats
8      16 sdb 768 713 11834 6968 13710 6808 12970792 6846477 0 76967 6853359
...

A quarta coluna (que conta leituras) indica que apenas 1 leitura ocorreu, apesar de você ter solicitado leituras de 1 byte. Esse é o comportamento esperado, pois esse dispositivo (um disco SATA 2) deve retornar no mínimo o tamanho do setor. O kernel simplesmente está armazenando em cache todo o setor.

O principal fator em jogo nessas solicitações de tamanho é a sobrecarga de emitir uma chamada do sistema para leitura ou gravação. De fato, emitir a chamada para <512 é ineficiente. Leituras muito grandes requerem menos chamadas do sistema ao custo de mais memória sendo usada para isso.

4096 é normalmente um número 'seguro' para leitura porque:

  • Ao ler com o cache ativado (o padrão), uma página é 4k. Preencher uma página com <4k leituras é mais complicado do que manter a leitura e o tamanho da página iguais.
  • A maioria dos tamanhos de bloco do sistema de arquivos é definida como 4k.
  • Não é um número pequeno o suficiente (talvez para SSDs agora) causar sobrecarga do syscall, mas não um número grande o suficiente para consumir muita memória.
Matthew Ife
fonte