Por que canalizar 'dd' através do gzip é muito mais rápido que uma cópia direta?

79

Eu queria fazer o backup de um caminho de um computador na minha rede para outro computador na mesma rede em uma linha de 100 Mbit / s. Por isso eu fiz

dd if=/local/path of=/remote/path/in/local/network/backup.img

o que me proporcionou uma velocidade de transferência de rede muito baixa, algo em torno de 50 a 100 kB / s, o que levaria uma eternidade. Então eu parei e decidi tentar compactá-lo em tempo real para torná-lo muito menor, para que a quantidade a transferir seja menor. Então eu fiz

dd if=/local/path | gzip > /remote/path/in/local/network/backup.img.gz

Mas agora eu tenho algo como 1 MB / s de velocidade de transferência de rede, então um fator de 10 a 20 mais rápido. Depois de perceber isso, testei isso em vários caminhos e arquivos, e sempre foi o mesmo.

Por que a tubulação ddatravés de gziptambém aumentar as taxas de transferência por um fator grande em vez de reduzir somente o ByteLength do fluxo por um fator de grande porte? Eu esperava até uma pequena redução nas taxas de transferência, devido ao maior consumo de CPU durante a compactação, mas agora recebo uma vantagem dupla. Não que eu não esteja feliz, mas estou apenas pensando. ;)

Foo Bar
fonte
1
512 bytes era o tamanho padrão do bloco para armazenamento de arquivos no início do Unix. Como tudo é um arquivo no Unix / Linux, tornou-se o padrão para quase tudo. As versões mais recentes da maioria dos utilitários aumentaram isso, mas não o dd.
precisa saber é o seguinte
A resposta simples é que a ddsaída é de 1 MB / s ... diretamente no canal em espera gzip. Tem muito pouco a ver com o tamanho do bloco.
Tullo_x86

Respostas:

100

ddpor padrão, usa um tamanho de bloco muito pequeno - 512 bytes (!!). Ou seja, muitas pequenas leituras e gravações. Parece que dd, usado ingenuamente em seu primeiro exemplo, estava gerando um grande número de pacotes de rede com uma carga útil muito pequena, reduzindo assim a taxa de transferência.

Por outro lado, gzipé inteligente o suficiente para fazer E / S com buffers maiores. Ou seja, um número menor de grandes gravações na rede.

Você pode tentar ddnovamente com um bs=parâmetro maior e ver se funciona melhor desta vez?


fonte
20
Obrigado, tentei a cópia direta sem gzip e um tamanho de bloco de bs=10M-> rápida transferência de rede de algo em torno de 3 ou 4 MB / s. Maior tamanho de bloco gzipnão mudou nada em comparação com pequeno tamanho de bloco gzip.
Foo Bar
7
Se você quiser ver quais tamanhos de bloco altos, tente outro dd após o gzip.
Joshua
O gzip está fazendo seu próprio buffer de saída ou apenas usa o stdio?
Barmar 30/05
@ Barmar Se estou lendo a fonte corretamente, é simplesmente write(3)para o buffer.
@CongMa você também pode tentar usar pigz vez de gzip, ele vai trabalhar ainda mais rápido
GioMac
4

Um pouco tarde para isso, mas devo acrescentar ...

Em uma entrevista, uma vez me perguntaram qual seria o método mais rápido possível para clonar dados bit a bit e de respostas grosseiras com o uso de ddou dc3dd( financiado pelo Departamento de Defesa ). O entrevistador confirmou que a tubulação ddpara ddé mais eficiente, pois isso simplesmente permite simultânea leitura / gravação ou em termos programador stdin/stdout, assim ultimatly duplicação da velocidade de gravação e tempo de transferência Halfing.

dc3dd verb=on if=/media/backup.img | dc3dd of=/dev/sdb
Sadik Tekin
fonte
1
Eu não acho que seja verdade. Eu apenas tentei agora. dd status=progress if=/dev/zero count=100000 bs=1M of=/dev/nullera 22,5 GB / s, dd status=progress if=/dev/zero count=100000 bs=1M | dd of=/dev/null bs=1Mera 2,7 GB. Então o tubo torna mais lento.
falsePockets 25/02
0

Cong está correto. Você está transmitindo os blocos do disco não compactado para um host remoto. Sua interface de rede, rede e seu servidor remoto são a limitação. Primeiro, você precisa melhorar o desempenho do DD. A especificação de um parâmetro bs = alinhado com a memória buffer do disco obterá o máximo desempenho do disco. Diga bs = 32M, por exemplo. Isso preencherá o buffer do gzip na taxa de linha sata ou sas diretamente do buffer das unidades. O disco estará mais inclinado à transferência sequencial, oferecendo melhor através da colocação. O Gzip comprimirá os dados no fluxo e os enviará para a sua localização. Se você estiver usando NFS, isso permitirá que a transmissão nfs seja mínima. Se você estiver usando SSH, você cobrirá a sobrecarga de encapsulamento e criptografia SSH. Se você usa o netcat, não há nenhuma sobrecarga de criptografia.

Robert
fonte
0

Suponho aqui que a "velocidade de transferência" a que você está se referindo esteja sendo relatada por dd. Isso realmente faz sentido, porque ddna verdade está transferindo 10x a quantidade de dados por segundo ! No entanto, ddnão está sendo transferido pela rede - esse trabalho está sendo tratado pelo gzipprocesso.

Algum contexto: gzipconsumirá os dados de seu canal de entrada o mais rápido que puder limpar seu buffer interno. A velocidade na qual gzipo buffer esvazia depende de alguns fatores:

  • A largura de banda de gravação de E / S (que é afunilada pela rede e permaneceu constante)
  • A largura de banda de leitura de E / S (que será muito superior a 1 MB / s de leitura de um disco local em uma máquina moderna, portanto, não é um provável gargalo)
  • Sua taxa de compactação (que eu assumirei pela sua aceleração de 10x em cerca de 10%, indicando que você está compactando algum tipo de texto altamente repetitivo como um arquivo de log ou XML)

Portanto, neste caso, a rede pode lidar com 100kB / s e gzipestá compactando os dados em torno de 10: 1 (e não está sendo afetado pela CPU). Isso significa que, enquanto produz 100kB / s, gzippode consumir 1MB / s, e a taxa de consumo é o que ddpode ver.

Tullo_x86
fonte