LZMA/LZMA2-Algorithmus ( xz, 7z)

LZMA/LZMA2-Algorithmus ( xz, 7z)

Ich habe gerade ein kleines Experiment gemacht, bei dem ich ein Tar-Archiv mit doppelten Dateien erstellt habe, um zu sehen, ob es komprimiert wird. Zu meinem Erstaunen war dies nicht der Fall! Einzelheiten folgen (Ergebnisse eingerückt, damit Sie sie leichter lesen können):

$ dd if=/dev/urandom bs=1M count=1 of=a
  1+0 records in
  1+0 records out
  1048576 bytes (1.0 MB) copied, 0.114354 s, 9.2 MB/s
$ cp a b
$ ln a c
$ ll
  total 3072
  -rw-r--r-- 2 guido guido 1048576 Sep 24 15:51 a
  -rw-r--r-- 1 guido guido 1048576 Sep 24 15:51 b
  -rw-r--r-- 2 guido guido 1048576 Sep 24 15:51 c
$ tar -c * -f test.tar
$ ls -l test.tar 
  -rw-r--r-- 1 guido guido 2109440 Sep 24 15:51 test.tar
$ gzip test.tar 
$ ls -l test.tar.gz 
  -rw-r--r-- 1 guido guido 2097921 Sep 24 15:51 test.tar.gz
$ 

Zuerst habe ich eine 1-MiB-Datei mit zufälligen Daten erstellt (a). Dann habe ich sie in eine Datei b kopiert und sie auch mit c verknüpft. Beim Erstellen des Tarballs war sich Tar anscheinend des Hardlinks bewusst, da der Tarball nur ~2MiB und nicht ~3Mib groß war.

Nun hatte ich erwartet, dass gzip die Größe des Tarballs auf ca. 1 MiB reduziert, da a und b Duplikate sind und im Tarball 1 MiB fortlaufender Daten wiederholt werden sollten. Dies geschah jedoch nicht.

Warum ist das so? Und wie kann ich das Tarball in diesen Fällen effizient komprimieren?

Antwort1

Gzip gzip basiert auf dem DEFLATE-Algorithmus, einer Kombination aus LZ77- und Huffman-Kodierung. Es handelt sich um einen verlustfreien Datenkomprimierungsalgorithmus, der den Eingabestrom mithilfe eines im laufenden Betrieb erstellten Wörterbuchs in komprimierte Symbole umwandelt und nach Duplikaten sucht. Er kann jedoch keine Duplikate finden, die mehr als 32 KB voneinander entfernt sind. Es ist nicht realistisch zu erwarten, dass er Duplikate erkennt, die 1 MB voneinander entfernt sind.

Antwort2

Nicole Hamilton bemerkt richtigdas gzipaufgrund seiner geringen Wörterbuchgröße keine entfernten doppelten Daten findet.

bzip2ist ähnlich, da es auf 900 KB Speicher begrenzt ist.

Versuchen Sie stattdessen:

LZMA/LZMA2-Algorithmus ( xz, 7z)

Der LZMA-Algorithmus gehört zur selben Familie wie Deflate, verwendet aber eine viel größere Wörterbuchgröße (anpassbar; Standard ist etwa 384 MB). Das xzDienstprogramm, das auf den meisten aktuellen Linux-Distributionen standardmäßig installiert sein sollte, ist ähnlich wie gzipLZMA und verwendet es auch.

Da LZMA Redundanz über größere Entfernungen erkennt, kann es Ihre Daten hier deduplizieren. Es ist jedoch langsamer als Gzip.

Eine weitere Option ist 7-zip ( 7zim p7zipPaket ), ein Archivierungsprogramm (anstelle eines Single-Stream-Kompressors), das standardmäßig LZMA verwendet (geschrieben vom Autor von LZMA). Das 7-Zip-Archivierungsprogramm führt seine eigene Deduplizierung auf Dateiebene aus (unter Berücksichtigung von Dateien mit derselben Erweiterung), wenn es in sein .7zFormat archiviert. Das bedeutet, dass Sie identische Dateien dedupliziert bekommen, wenn Sie bereit sind, tardurch zu ersetzen 7z. 7z bewahrt jedoch keine Nanosekunden-Zeitstempel, Berechtigungen oder xattrs auf, sodass es Ihren Anforderungen möglicherweise nicht entspricht.

lrzip

lrzipist ein Kompressor, der die Daten vorverarbeitet, um Redundanzen über große Entfernungen zu entfernen, bevor sie einem herkömmlichen Algorithmus wie Gzip/Deflate, bzip2, lzop oder LZMA zugeführt werden. Für die Beispieldaten, die Sie hier angeben, ist dies nicht erforderlich. Es ist nützlich, wenn die Eingabedaten größer sind als das, was in den Speicher passt.

Für diese Art von Daten (duplizierte, nicht komprimierbare Blöcke) sollten Sie lzopdie Komprimierung (sehr schnell) mit verwenden lrzip, da es keinen Vorteil bringt, nach der Deduplizierung stärker zu versuchen, völlig zufällige Daten zu komprimieren.

Bup und Obnam

Da Sie die Frage markiert habenWenn Ihr Ziel hier die Datensicherung ist, sollten Sie ein deduplizierendes Backup-Programm verwenden wieBupoderObnam.

Antwort3

gzipfindet keine Duplikate, selbst xzbei einem riesigen Wörterbuch nicht. Was Sie tun können, ist zu verwenden mksquashfs– dadurch wird tatsächlich Platz für Duplikate gespart.

Einige schnelle Testergebnisse mit xzund mksquashfsmit drei zufälligen Binärdateien (64 MB), von denen zwei gleich sind:

Aufstellen:

mkdir test
cd test
dd if=/dev/urandom of=test1.bin count=64k bs=1k
dd if=/dev/urandom of=test2.bin count=64k bs=1k
cp test{2,3}.bin
cd ..

Squashfs:

mksquashfs test/ test.squash
> test.squash - 129M

xz:

XZ_OPT='-v --memlimit-compress=6G --memlimit-decompress=512M --lzma2=preset=9e,dict=512M --extreme -T4 ' tar -cJvf test.tar.xz test/
> test.tar.xz - 193M

Antwort4

Als Ergänzung zur Antwort der „mechanischen Schnecke“:

Sogar xz (oder lzma) findet keine Duplikate, wenn die Dateigröße der unkomprimierten Einzeldatei (oder genauer gesagt der Abstand zwischen den Duplikaten) die Wörterbuchgröße überschreitet. xz (oder lzma) -9ereserviert selbst bei der höchsten Einstellung nur 64 MB hierfür.

Glücklicherweise können Sie mit der Option Ihre eigene Wörterbuchgröße angeben --lzma2=dict=256MB ( --lzma1=dict=256MBist nur zulässig, wenn Sie den lzma-Alias ​​für den Befehl verwenden).

Wenn die Einstellungen mit benutzerdefinierten Komprimierungsketten wie im obigen Beispiel überschrieben werden, werden die Standardwerte für alle anderen Parameter leider nicht auf das gleiche Niveau gesetzt wie bei -9e. Daher ist die Komprimierungsdichte für einzelne Dateien nicht so hoch.

verwandte Informationen