Копирование разреженного файла размером 1 ТБ

У меня есть разреженный файл размером 1 ТБ, в котором фактически хранится 32 МБ данных в Linux.

Можно ли «эффективно» создать пакет для хранения разреженного файла? Пакет должен быть распакован в разреженный файл размером 1 ТБ на другом компьютере. В идеале «пакет» должен быть около 32 МБ.

Примечание. Возможным решением является использование tar: https://wiki.archlinux.org/index.php/Sparse_file#Archiving_with_.60tar.27

Однако для разреженного файла размером 1 ТБ, несмотря на то, что tar-шар может быть небольшим, архивирование разреженного файла займет слишком много времени.

Изменить 1

Я протестировал tar и gzip, и результаты следующие (обратите внимание, что этот разреженный файл содержит данные размером 0 байт).

$ du -hs sparse-1
0   sparse-1

$ ls -lha sparse-1
-rw-rw-r-- 1 user1 user1 1.0T 2012-11-03 11:17 sparse-1

$ time tar cSf sparse-1.tar sparse-1

real    96m19.847s
user    22m3.314s
sys     52m32.272s

$ time gzip sparse-1

real    200m18.714s
user    164m33.835s
sys     10m39.971s

$ ls -lha sparse-1*
-rw-rw-r-- 1 user1 user1 1018M 2012-11-03 11:17 sparse-1.gz
-rw-rw-r-- 1 user1 user1   10K 2012-11-06 23:13 sparse-1.tar

Файл sparse-1 размером 1 ТБ, содержащий 0 байт данных, может быть заархивирован с помощью «tar» в tar-шар размером 10 КБ или сжат с помощью gzip до файла размером ~ 1 ГБ. gzip занимает примерно в 2 раза больше времени, чем tar.

Из сравнения «tar» кажется лучше, чем gzip.

Однако 96 минут слишком много для разреженного файла, содержащего данные размером 0 байт.

Изменить 2

rsync кажется, что копирование файла занимает больше времени, чем tar, но меньше, чем gzip:

$ time rsync --sparse sparse-1 sparse-1-copy

real    124m46.321s
user    107m15.084s
sys     83m8.323s

$ du -hs sparse-1-copy 
4.0K    sparse-1-copy

Следовательно, tar + cp или scp должно быть быстрее, чем непосредственно rsync для этого чрезвычайно разреженного файла.

Изменить 3

Спасибо @mvp за указание на функциональность SEEK_HOLE в новом ядре. (Ранее я работал над ядром Linux версии 2.6.32).

Примечание. Требуется версия bsdtar >=3.0.4 (см. здесь: http://ask.fclose.com/4/how-to-efficiently-archive-a-very-large-sparse-file?show=299#c299 ).

В новом ядре и выпуске Fedora (17) tar и cp обрабатывают разреженный файл очень эффективно.

[zma@office tmp]$ ls -lh pmem-1 

-rw-rw-r-- 1 zma zma 1.0T Nov  7 20:14 pmem-1
[zma@office tmp]$ time tar cSf pmem-1.tar pmem-1

real    0m0.003s
user    0m0.003s
sys 0m0.000s
[zma@office tmp]$ time cp pmem-1 pmem-1-copy

real    0m0.020s
user    0m0.000s
sys 0m0.003s
[zma@office tmp]$ ls -lh pmem*
-rw-rw-r-- 1 zma zma 1.0T Nov  7 20:14 pmem-1
-rw-rw-r-- 1 zma zma 1.0T Nov  7 20:15 pmem-1-copy
-rw-rw-r-- 1 zma zma  10K Nov  7 20:15 pmem-1.tar
[zma@office tmp]$ mkdir t
[zma@office tmp]$ cd t
[zma@office t]$ time tar xSf ../pmem-1.tar 

real    0m0.003s
user    0m0.000s
sys 0m0.002s
[zma@office t]$ ls -lha
total 8.0K
drwxrwxr-x   2 zma  zma  4.0K Nov  7 20:16 .
drwxrwxrwt. 35 root root 4.0K Nov  7 20:16 ..
-rw-rw-r--   1 zma  zma  1.0T Nov  7 20:14 pmem-1

Я использую ядро ​​​​3.6.5:

[zma@office t]$ uname -a
Linux office.zhiqiangma.com 3.6.5-1.fc17.x86_64 #1 SMP Wed Oct 31 19:37:18 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

person ericzma    schedule 06.11.2012    source источник
comment
gzip или bzip2 должны прекрасно сжимать его. pigz и pbzip2 — их соответствующие современные эквиваленты, использующие все ядра. Вы будете приятно удивлены, как быстро они бегают.   -  person Marcin    schedule 06.11.2012
comment
Сжатие @Marcin с помощью gzip кажется хуже, чем tar. Пожалуйста, найдите обновленный вопрос с результатами gzip и tar.   -  person ericzma    schedule 07.11.2012
comment
Когда вы говорите разреженный файл из 0 байтов, вы имеете в виду, что каждый байт равен 0? Это другой вопрос.   -  person Matthew Strawbridge    schedule 07.11.2012
comment
@MatthewStrawbridge Я имел в виду, что разреженный файл содержит данные размером 0 байт (нет данных).   -  person ericzma    schedule 07.11.2012
comment
Ничего себе, это действительно мало ;-) В этом случае вы можете сжать его до одного значения: количество байтов в файле!   -  person Matthew Strawbridge    schedule 07.11.2012
comment
gzip ужасно плохо работает с данными, содержащими длинные строки повторяющихся символов. LZMA не намного лучше. длинные отрезки 0, 1 или что-то еще эффектно сжимаются bzip. У меня был файл размером 1,8 ГБ, в основном (90%) с нулями и остальными случайными целыми числами. он был сжат примерно до 800 КБ. однако скорость хромает.   -  person staticd    schedule 07.10.2013


Ответы (4)


Краткий ответ: используйте bsdtar или GNU tar (версия 1.29 или более поздняя) для создания архивов и GNU tar (версия 1.26 или более поздняя) для их извлечения на другом компьютере.

Длинный ответ: для этого необходимо выполнить некоторые требования.

Во-первых, Linux должен иметь ядро ​​не ниже 3.1 (подойдет Ubuntu 12.04 или более поздняя версия), чтобы он поддерживал функциональность SEEK_HOLE.

Затем вам нужна утилита tar, которая может поддерживать этот системный вызов. GNU tar поддерживает его, начиная с версии 1.29 (выпущена 16 мая 2016 г., он должен присутствовать по умолчанию, начиная с Ubuntu 18.04), или bsdtar, начиная с версии 3.0.4 (доступен, начиная с Ubuntu 12.04) — установите его с помощью sudo apt-get install bsdtar.

В то время как bsdtar (который использует libarchive) великолепен, к сожалению, он не очень умен, когда дело доходит до распаковки - он по глупости требует, чтобы на целевом диске было как минимум столько же свободного места, сколько размер файла без смолы, без учета дыр. GNU tar эффективно распаковывает такие разреженные архивы и не проверяет это условие.

Это журнал из Ubuntu 12.10 (ядро Linux 3.5):

$ dd if=/dev/zero of=1tb seek=1T bs=1 count=1
1+0 records in
1+0 records out
1 byte (1 B) copied, 0.000143113 s, 7.0 kB/s

$ time bsdtar cvfz sparse.tar.gz 1tb 
a 1tb

real    0m0.362s
user    0m0.336s
sys 0m0.020s

# Or, use gnu tar if version is later than 1.29:
$ time tar cSvfz sparse-gnutar.tar.gz 1tb
1tb

real    0m0.005s
user    0m0.006s
sys 0m0.000s

$ ls -l
-rw-rw-r-- 1 autouser autouser 1099511627777 Nov  7 01:43 1tb
-rw-rw-r-- 1 autouser autouser           257 Nov  7 01:43 sparse.tar.gz
-rw-rw-r-- 1 autouser autouser           134 Nov  7 01:43 sparse-gnutar.tar.gz
$

Как я уже сказал выше, к сожалению, распаковка с помощью bsdtar не будет работать, если у вас нет 1 ТБ свободного места. Однако любая версия GNU tar отлично справляется с распаковкой таких sparse.tar:

$ rm 1tb 
$ time tar -xvSf sparse.tar.gz 
1tb

real    0m0.031s
user    0m0.016s
sys 0m0.016s
$ ls -l
total 8
-rw-rw-r-- 1 autouser autouser 1099511627777 Nov  7 01:43 1tb
-rw-rw-r-- 1 autouser autouser           257 Nov  7 01:43 sparse.tar.gz
person mvp    schedule 07.11.2012
comment
Потрясающий! Думаю, SEEK_HOLE играет свою роль! Я попробовал tar и cp на ядре Linux 3.6.5, и оба они очень быстрые. Спасибо! - person ericzma; 07.11.2012
comment
Справедливо ли требование ядра Linux 3.1 или более поздней версии, даже если используется более поздняя версия libarchive? Похоже, есть код, который использует IOCTL FIEMAP в версиях 3.x libarchive. github.com/libarchive/libarchive/blob/master/libarchive/ - person bockmabe; 22.10.2013
comment
К сожалению, спустя 1,5 года после того, как я написал это, GNU tar все еще не научилась эффективно анализировать дыры, поэтому этот рецепт все еще очень актуален! :(... - person mvp; 22.05.2014
comment
Я попробовал это с пустым разреженным файлом размером 1 МБ и обнаружил, что bsdtar обрабатывает его как неразреженный файл. Для разреженного файла размером 2 ТБ с чем-то посередине это работало так, как описано выше. Может быть, это работает только для очень больших файлов? - person Alfe; 08.09.2017
comment
Наконец, GNU tar поддерживает это должным образом, начиная с версии 1.29 ;-) - person mvp; 19.09.2019

Я понимаю, что этот вопрос очень старый, но вот обновление, которое может быть полезно для других, которые находят свой путь здесь так же, как и я.

К счастью, отличный ответ mvp устарел. Согласно примечаниям к выпуску tar, SEEK_HOLE/SEEK_DATA были добавлены в версии 1.29, выпущенной 2016-05-16. (А поскольку GNU tar v. 1.30 теперь является стандартным в стабильной версии Debian, можно с уверенностью предположить, что версия tar ≥ 1.29 доступна почти везде.)

Таким образом, теперь способ обработки разреженных файлов заключается в том, чтобы заархивировать их с помощью любого установленного в вашей системе tar (GNU или BSD), и то же самое для извлечения.

Кроме того, для разреженных файлов, которые на самом деле содержат некоторые данные, стоит ли использовать сжатие (т. е. данные достаточно сжимаемы, чтобы сэкономить значительное место на диске, а экономия места на диске стоит вероятного значительного времени и ресурсов ЦП, необходимых для его сжатия) :

  • tar -cSjf <archive>.tar.bz2 /path/to/sparse/file будет использовать функциональность tar SEEK_HOLE для быстрого и эффективного архивирования разреженного файла, а также использовать bzip2 для сжатия фактических данных.
  • tar --use-compress-program=pbzip2 -cSf <archive>.tar.bz2 /path/to/sparse/file, как упоминалось в комментарии marcin, будет делать то же самое, также используя несколько ядер для задачи сжатия.

На моем маленьком домашнем сервере с четырехъядерным процессором Atom использование pbzip2 против bzip2 сократило время примерно на 25 или 30%.

Со сжатием или без него это даст вам архив, который не требует какой-либо специальной обработки разреженных файлов, занимает примерно «реальный» размер исходного разреженного файла (или меньше, если он сжат), и его можно перемещать, не беспокоясь. о несоответствии возможностей разреженных файлов разных утилит. Например: cp автоматически обнаружит разреженные файлы и сделает все правильно, rsync правильно обработает разреженные файлы, если вы используете флаг -S, а scp не имеет опции для разреженных файлов (будет потребляться полоса пропускания, копируя нули для всех дыр, и в результате копия будет неразреженным файлом, размер которого равен «видимому» размеру оригинала); но все они, конечно, прекрасно справятся с tar-архивом — независимо от того, содержит он разреженные файлы или нет — без каких-либо специальных флагов.

Дополнительные примечания

  1. При извлечении tar автоматически обнаружит архив, созданный с помощью -S, поэтому указывать его не нужно.
  2. Архив, созданный с помощью pbzip2, хранится фрагментами. Это приводит к тому, что архив немного больше, чем при использовании bzip2, но также означает, что извлечение может быть многопоточным, в отличие от архива, созданного с помощью bzip2.
  3. pbzip2 и bzip2 будут надежно извлекать архивы друг друга без ошибок и повреждений.
person Askeli    schedule 13.09.2019
comment
Спасибо за уведомление о tar 1.29 — это отличная новость! Кстати, современная утилита cp автоматически использует это и эффективно копирует разреженные файлы. - person mvp; 19.09.2019
comment
Хороший вопрос, @mvp, я отредактировал свой ответ, чтобы прояснить эту часть. - person Askeli; 20.09.2019

Из связанного вопроса, возможно, rsync будет работать:

rsync --sparse sparse-1 sparse-1-copy
person wallyk    schedule 07.11.2012
comment
Я попробовал это и через несколько минут убил его, так как он кажется очень загруженным (два процесса rsync, которые занимают ~ 89% и ~ 62% ЦП). Я не ожидаю, что rsync подойдет для этой цели лучше, чем tar. Но я попробую еще раз, так как сервер в настоящее время простаивает. - person ericzma; 07.11.2012
comment
Похоже, что rsync закончил копирование файла быстрее, чем tar, но меньше, чем gzip. Результаты находятся в Редактировать 2 вопроса. - person ericzma; 07.11.2012
comment
rsync не является быстрой или эффективной программой для копирования файлов с диска на диск, но у нее есть много возможностей, которые вы не найдете больше нигде. Вы можете использовать rsync -S ... для копирования разреженных файлов по локальной сети, например, по ssh. Для копирования с диска на диск просто используйте cp --sparse=<option>, для максимального разрежения используйте параметр always - person James Stevens; 12.11.2020
comment
@Джеймс: Спасибо! Удивительно, как развились эти утилиты. - person wallyk; 12.11.2020

Вы определенно ищете инструмент сжатия, такой как tar, lzma, bzip2, zip или rar. Согласно этому сайту, lzma довольно быстрый, но при этом имеет довольно хорошую степень сжатия:

http://blog.terzza.com/linux-compression-comparison-gzip-vs-bzip2-vs-lzma-vs-zip-vs-compress/

Вы также можете настроить соотношение скорость/качество сжатия, установив уровень сжатия на что-то низкое, немного поэкспериментируйте, чтобы найти уровень, который работает лучше всего.

http://linux.die.net/man/1/unlzma

person LukeGT    schedule 06.11.2012
comment
Сжатие с помощью gzip кажется хуже, чем простое архивирование файла с помощью tar. Пожалуйста, найдите обновленный вопрос с результатами gzip и tar. Архивирование кажется все еще слишком медленным для обработки файла, содержащего 0 байт. - person ericzma; 07.11.2012
comment
Bzip имеет самую низкую скорость распаковки среди gz и LZMA для всех степеней сжатия. - person staticd; 07.10.2013
comment
Спасибо @staticd, я неправильно прочитал график. Я удалил эту рекомендацию из своего ответа. - person LukeGT; 18.02.2017