Mengapa pemipaan 'dd' melalui gzip jauh lebih cepat daripada salinan langsung?

79

Saya ingin membuat cadangan jalur dari komputer di jaringan saya ke komputer lain di jaringan yang sama melalui jalur 100 Mbit / s. Untuk ini saya lakukan

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

yang memberi saya kecepatan transfer jaringan yang sangat rendah sekitar 50 hingga 100 kB / s, yang akan memakan waktu selamanya. Jadi saya menghentikannya dan memutuskan untuk mencoba gzip dengan cepat agar lebih kecil sehingga jumlah yang ditransfer lebih sedikit. Jadi saya lakukan

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

Tapi sekarang saya mendapatkan kecepatan transfer jaringan 1 MB / s, jadi faktor 10 hingga 20 lebih cepat. Setelah memperhatikan ini, saya menguji ini pada beberapa jalur dan file, dan selalu sama.

Mengapa perpipaan ddmelalui gzipjuga meningkatkan kecepatan transfer dengan faktor besar, bukan hanya mengurangi panjang gelombang aliran dengan faktor besar? Saya bahkan mengharapkan penurunan kecil dalam kecepatan transfer, karena konsumsi CPU yang lebih tinggi saat mengompresi, tapi sekarang saya mendapatkan nilai tambah ganda. Bukannya aku tidak bahagia, tapi aku hanya ingin tahu. ;)

Foo Bar
sumber
1
512 byte adalah ukuran blok standar untuk penyimpanan file di Unix awal. Karena semuanya adalah file di Unix / Linux, itu menjadi default untuk semuanya. Versi yang lebih baru dari sebagian besar utilitas telah meningkatkannya tetapi tidak dd.
DocSalvager
Jawaban sederhananya ddadalah keluaran 1MB / s ... langsung ke gzippipa tunggu . Sangat sedikit hubungannya dengan ukuran blok.
Tullo_x86

Jawaban:

100

ddsecara default menggunakan ukuran blok yang sangat kecil - 512 byte (!!). Artinya, banyak yang membaca dan menulis. Tampaknya dd, digunakan secara naif dalam contoh pertama Anda, menghasilkan banyak paket jaringan dengan muatan yang sangat kecil, sehingga mengurangi throughput.

Di sisi lain, gzipcukup pintar untuk melakukan I / O dengan buffer yang lebih besar. Artinya, sejumlah kecil tulisan besar melalui jaringan.

Bisakah Anda mencoba ddlagi dengan bs=parameter yang lebih besar dan melihat apakah itu berfungsi lebih baik kali ini?


sumber
20
Terima kasih, coba copy langsung tanpa gzip dan bloksi bs=10M-> transfer jaringan cepat sesuatu sekitar 3 atau 4 MB / s. Blocksize lebih tinggi + gziptidak mengubah apa pun dibandingkan + kecil blocksize gzip.
Foo Bar
7
Jika Anda ingin melihat ukuran blok tinggi apa coba lagi dd setelah gzip.
Joshua
Apakah gzip melakukan buffering output sendiri, atau hanya menggunakan stdio?
Barmar
@Barmar Jika saya membaca sumber dengan benar, itu hanya write(3)untuk buffer.
@CongMa Anda juga dapat mencoba dan menggunakan pigz alih-alih gzip, ini akan bekerja lebih cepat
GioMac
4

Agak terlambat untuk ini tetapi mungkin saya tambahkan ...

Dalam sebuah wawancara saya pernah ditanya apa yang akan menjadi metode tercepat untuk kloning data bit-for-bit dan dari tanggapan kasar dengan penggunaan ddatau dc3dd( didanai DoD ). Pewawancara mengkonfirmasikan bahwa perpipaan ddke ddlebih efisien, karena ini hanya memungkinkan Baca / Tulis simultan atau dalam istilah programmer stdin/stdout, sehingga dua kali lipat kecepatan tulis dan separuh waktu transfer.

dc3dd verb=on if=/media/backup.img | dc3dd of=/dev/sdb
Sadik Tekin
sumber
1
Saya pikir itu tidak benar. Saya baru saja mencoba sekarang. dd status=progress if=/dev/zero count=100000 bs=1M of=/dev/nulladalah 22.5GB / s, dd status=progress if=/dev/zero count=100000 bs=1M | dd of=/dev/null bs=1Madalah 2.7GB. Jadi pipa membuatnya lebih lambat.
falsePockets
0

Cong benar. Anda mengalirkan blok dari disk yang tidak dikompresi ke host jarak jauh. Antarmuka jaringan, jaringan, dan server jarak jauh Anda adalah batasannya. Pertama, Anda perlu meningkatkan kinerja DD. Menentukan parameter bs = yang sejajar dengan memori buffer disk akan mendapatkan kinerja maksimal dari disk. Katakanlah bs = 32M misalnya. Ini kemudian akan mengisi buffer gzip di sata atau selisih laju garis sas dari buffer drive. Disk akan lebih condong ke transfer sekuensial yang memberi hasil lebih baik melalui put. Gzip akan memampatkan data dalam aliran dan mengirimkannya ke lokasi Anda. Jika Anda menggunakan NFS yang memungkinkan transmisi nfs menjadi minimal. Jika Anda menggunakan SSH maka Anda membungkus enkapsulasi dan enkripsi SSH. Jika Anda menggunakan netcat maka Anda tidak memiliki enkripsi di atas kepala.

Robert
sumber
0

Saya berasumsi di sini bahwa "kecepatan transfer" yang Anda maksud sedang dilaporkan oleh dd. Ini sebenarnya masuk akal, karena ddsebenarnya mentransfer 10x jumlah data per detik ! Namun, ddtidak mentransfer melalui jaringan - pekerjaan itu sedang ditangani oleh gzipproses.

Beberapa konteks: gzipakan mengkonsumsi data dari pipa input secepat mungkin dapat menghapus buffer internal. Kecepatan gzipbuffer kosong tergantung pada beberapa faktor:

  • I / O write bandwidth (yang mengalami hambatan oleh jaringan, dan tetap konstan)
  • Bandwidth baca I / O (yang akan jauh lebih tinggi dari 1MB / s membaca dari disk lokal pada mesin modern, dengan demikian tidak mungkin menjadi hambatan)
  • Rasio kompresinya (yang saya anggap oleh kecepatan 10x Anda menjadi sekitar 10%, menunjukkan bahwa Anda mengompres beberapa jenis teks yang sangat berulang seperti file log atau XML)

Jadi dalam hal ini, jaringan dapat menangani 100kB / s, dan gzipmengompresi data sekitar 10: 1 (dan tidak dihambat oleh CPU). Ini berarti bahwa sementara itu mengeluarkan 100kB / s, gzipdapat mengkonsumsi 1MB / s, dan tingkat konsumsi adalah apa yang ddbisa dilihat.

Tullo_x86
sumber