Почему передача 'dd' через gzip намного быстрее, чем прямая копия?

79

Я хотел сделать резервную копию пути от компьютера в моей сети к другому компьютеру в той же сети по линии 100 Мбит / с. Для этого я сделал

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

что дало мне очень низкую скорость передачи данных по сети, порядка 50-100 кБ / с, что заняло бы целую вечность. Поэтому я остановил его и решил попробовать распаковать его на лету, чтобы сделать его намного меньше, чтобы сумма перевода была меньше. Так я и сделал

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

Но теперь я получаю примерно 1 МБ / с скорости передачи по сети, так что в 10-20 раз быстрее. Заметив это, я проверил это на нескольких путях и файлах, и это всегда было одинаково.

Почему ddпрохождение по трубопроводу gzipтакже увеличивает скорость передачи в значительной степени, а не только уменьшает длину байта потока в значительной степени? Вместо этого я ожидал даже небольшого снижения скорости передачи из-за более высокого потребления ЦП при сжатии, но теперь я получаю двойной плюс. Не то чтобы я не был счастлив, но мне просто интересно. ;)

Фу Бар
источник
1
512 байт был стандартным размером блока для хранения файлов в ранних версиях Unix. Поскольку в Unix / Linux все является файлом, он стал по умолчанию практически для всего. Более новые версии большинства утилит увеличили это, но не дд.
DocSalvager
Простой ответ - это ddвывод со скоростью 1 МБ / с ... прямо в gzipканал ожидания . Это имеет очень мало общего с размером блока.
Tullo_x86

Ответы:

99

ddпо умолчанию используется очень маленький размер блока - 512 байт (!!). То есть много маленьких читает и пишет. Кажется, что dd, наивно использованный в вашем первом примере, генерировал большое количество сетевых пакетов с очень маленькой полезной нагрузкой, таким образом уменьшая пропускную способность.

С другой стороны, gzipдостаточно умен, чтобы делать ввод-вывод с большими буферами. То есть меньшее количество больших записей по сети.

Можете ли вы попробовать еще ddраз с большим bs=параметром и посмотреть, работает ли он лучше на этот раз?


источник
20
Спасибо, пробовал прямое копирование без gzip и размер блока bs=10M-> быстрая передача по сети что-то около 3 или 4 МБ / с. Более высокий размер блока gzipничего не изменил по сравнению с маленьким размером блока gzip.
Foo Bar
7
Если вы хотите увидеть, какие блоки имеют большой размер, попробуйте еще один dd после gzip.
Джошуа
Gzip выполняет собственную буферизацию вывода или использует только stdio?
Бармар
@ Barmar Если я правильно читаю источник, он просто помещается write(3)в буфер.
@CongMa, вы также можете попробовать использовать pigz вместо gzip, это будет работать еще быстрее
GioMac
4

Немного опоздал, но могу добавить ...

В одном из интервью меня как-то спросили, каким будет самый быстрый из возможных методов клонирования побитовых данных и грубых ответов с использованием ddили dc3dd( финансируется DoD ). Интервьюер подтвердил, что передача по каналу более эффективна, поскольку это просто позволяет одновременноdd выполнять чтение / запись или программисту , в результате чего скорость записи удваивается, а время передачи увеличивается вдвое.ddstdin/stdout

dc3dd verb=on if=/media/backup.img | dc3dd of=/dev/sdb
Садик Текин
источник
1
Я не думаю, что это правда. Я только что попробовал сейчас. dd status=progress if=/dev/zero count=100000 bs=1M of=/dev/nullбыло 22,5 ГБ / с, dd status=progress if=/dev/zero count=100000 bs=1M | dd of=/dev/null bs=1Mбыло 2,7 ГБ. Так что труба делает это медленнее.
falsePockets
0

Конг правильно. Вы передаете блоки с диска без сжатия на удаленный хост. Ваш сетевой интерфейс, сеть и ваш удаленный сервер являются ограничением. Сначала вам нужно повысить производительность DD. Задание параметра bs =, который выравнивается с буферной памятью дисков, обеспечит максимальную производительность диска. Например, bs = 32M. Затем он заполнит буфер gzip на скорости линии sata или sas из буфера накопителей. Диск будет более склонен к последовательной передаче, дающей лучше через пут. Gzip сожмет данные в поток и отправит их в ваше местоположение. Если вы используете NFS, это позволит минимизировать передачу nfs. Если вы используете SSH, то вы подвергаетесь инкапсуляции SSH и накладным расходам шифрования. Если вы используете netcat, то у вас нет шифрования над головой.

Роберт
источник
0

Здесь я предполагаю, что о «скорости передачи», на которую вы ссылаетесь, сообщается dd. Это действительно имеет смысл, потому что ddна самом деле скорость передачи данных в 10 раз выше, чем в секунду ! Однако ddне передается по сети - эта задача обрабатывается gzipпроцессом.

Некоторый контекст: gzipпотребляет данные из своего входного канала так быстро, как может очистить свой внутренний буфер. Скорость, с которой gzipочищается буфер, зависит от нескольких факторов:

  • Пропускная способность записи ввода / вывода (которая является узким местом в сети и остается постоянной)
  • Пропускная способность чтения ввода-вывода (которая будет намного выше, чем 1 МБ / с чтения с локального диска на современной машине, поэтому, скорее всего, не является узким местом)
  • Степень сжатия (которую я предполагаю при 10-кратном ускорении около 10%, что означает, что вы сжимаете какой-то высокоповторный текст, такой как файл журнала или какой-то XML)

Таким образом, в этом случае сеть может обрабатывать 100 кБ / с и gzipсжимает данные примерно в 10: 1 (и не является узким местом ЦП). Это означает, что, пока он выдает 100 КБ / с, он gzipможет потреблять 1 МБ / с, а скорость потребления - это то, что ddвидно.

Tullo_x86
источник