¿Por qué canalizar 'dd' a través de gzip es mucho más rápido que una copia directa?

79

Quería hacer una copia de seguridad de una ruta desde una computadora en mi red a otra computadora en la misma red a través de una línea de 100 Mbit / s. Por esto hice

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

lo que me dio una velocidad de transferencia de red muy baja de alrededor de 50 a 100 kB / s, lo que me habría llevado una eternidad. Así que lo detuve y decidí intentar comprimirlo sobre la marcha para hacerlo mucho más pequeño y que la cantidad a transferir sea menor. Así que lo hice

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

Pero ahora obtengo algo así como una velocidad de transferencia de red de 1 MB / s, por lo que es un factor de 10 a 20 más rápido. Después de notar esto, probé esto en varias rutas y archivos, y siempre fue lo mismo.

¿Por qué la tubería dda través gziptambién aumentan las tasas de transferencia por un factor grande en lugar de tan sólo reducir el ByteLength de la corriente por un factor de gran tamaño? En cambio, esperaba una pequeña disminución en las tasas de transferencia, debido al mayor consumo de CPU durante la compresión, pero ahora obtengo un doble plus. No es que no sea feliz, pero me pregunto. ;)

Foo Bar
fuente
1
512 bytes era el tamaño de bloque estándar para el almacenamiento de archivos a principios de Unix. Como todo es un archivo en Unix / Linux, se convirtió en el valor predeterminado para casi todo. Las versiones más nuevas de la mayoría de las utilidades han aumentado eso, pero no dd.
DocSalvager
La respuesta simple es que ddestá saliendo a 1MB / s ... directamente en la gziptubería de espera . Tiene muy poco que ver con el tamaño del bloque.
Tullo_x86

Respuestas:

100

ddpor defecto usa un tamaño de bloque muy pequeño: 512 bytes (!!). Es decir, muchas pequeñas lecturas y escrituras. Parece que dd, usado ingenuamente en su primer ejemplo, estaba generando una gran cantidad de paquetes de red con una carga útil muy pequeña, reduciendo así el rendimiento.

Por otro lado, gzipes lo suficientemente inteligente como para hacer E / S con buffers más grandes. Es decir, un número menor de grandes escrituras a través de la red.

¿Puedes volver dda intentarlo con un bs=parámetro más grande y ver si esta vez funciona mejor?


fuente
20
Gracias, probé la copia directa sin gzip y un tamaño de bloque de bs=10M-> transferencia de red rápida de algo así como 3 o 4 MB / s. Mayor tamaño de bloque + gzipno cambió nada en comparación con el pequeño tamaño de bloque + gzip.
Foo Bar
77
Si desea ver qué tamaños de bloque altos intentan con otro dd después del gzip.
Joshua
¿Gzip está haciendo su propio búfer de salida, o solo usa stdio?
Barmar
@Barmar Si estoy leyendo la fuente correctamente, simplemente write(3)está en el búfer.
@CongMa también puedes probar y usar pigz en lugar de gzip, funcionará aún más rápido
GioMac
4

Un poco tarde para esto, pero podría agregar ...

En una entrevista, una vez me preguntaron cuál sería el método más rápido posible para clonar datos bit por bit y, en términos generales, respondí con el uso de ddo dc3dd( financiado por el DoD ). El entrevistador confirmó que las tuberías ddque ddes más eficiente, ya que esto sólo permite simultánea de lectura / escritura o en términos programador stdin/stdout, por lo tanto ultimatly duplicar velocidades de escritura y el tiempo de transferencia de Halfing.

dc3dd verb=on if=/media/backup.img | dc3dd of=/dev/sdb
Sadik Tekin
fuente
1
No creo que sea verdad. Acabo de intentarlo ahora. dd status=progress if=/dev/zero count=100000 bs=1M of=/dev/nullera 22.5GB / s, dd status=progress if=/dev/zero count=100000 bs=1M | dd of=/dev/null bs=1Mera 2.7GB. Entonces la tubería lo hace más lento.
falsePockets
0

Cong es correcto. Está transmitiendo los bloques del disco sin comprimir a un host remoto. Su interfaz de red, red y su servidor remoto son la limitación. Primero necesitas aumentar el rendimiento de DD. Si especifica un parámetro bs = que se alinea con la memoria del búfer de discos, obtendrá el mayor rendimiento del disco. Decir bs = 32M por ejemplo. Esto llenará el búfer de gzip en el estrecho de velocidad de línea sata o sas del búfer de unidades. El disco estará más inclinado a la transferencia secuencial, lo que dará un mejor rendimiento. Gzip comprimirá los datos en secuencia y los enviará a su ubicación. Si está utilizando NFS, eso permitirá que la transmisión nfs sea mínima. Si está utilizando SSH, entonces aplica la sobrecarga de encapsulación y cifrado SSH. Si usa netcat, entonces no tiene cifrado por encima.

Robert
fuente
0

Asumo aquí que la "velocidad de transferencia" a la que te refieres está siendo informada por dd. ¡Esto realmente tiene sentido, porque en ddrealidad está transfiriendo 10 veces la cantidad de datos por segundo ! Sin embargo, ddno se está transfiriendo a través de la red, ese trabajo está siendo manejado por el gzipproceso.

Algún contexto: gzipconsumirá datos de su canal de entrada tan rápido como pueda borrar su búfer interno. La velocidad a la que se gzipvacía el búfer depende de algunos factores:

  • El ancho de banda de escritura de E / S (que está obstruido por la red y se ha mantenido constante)
  • El ancho de banda de lectura de E / S (que va a ser mucho mayor que la lectura de 1 MB / s desde un disco local en una máquina moderna, por lo tanto, no es un cuello de botella)
  • Su relación de compresión (que supongo que su aceleración 10x es de alrededor del 10%, lo que indica que está comprimiendo algún tipo de texto altamente repetitivo como un archivo de registro o algún XML)

Entonces, en este caso, la red puede manejar 100kB / s, y gzipestá comprimiendo los datos alrededor de 10: 1 (y la CPU no está bloqueada). Esto significa que mientras produce 100kB / s, gzippuede consumir 1MB / s, y la tasa de consumo es lo que ddpuede ver.

Tullo_x86
fuente