Schnell komprimieren mit lzop

gzip, bzip2, xz und 7zr (Paket p7zip) wurden im Hinblick auf immer bessere Komprimierung optimiert. Mit Erfolg. Aber wer damit GByte große Dateien (z.B. Images von virtuellen Maschinen) komprimieren will, braucht Geduld. Wenn’s schnell gehen soll, empfiehlt sich das weniger bekannte Kommando lzop.

Kurz eine Beschreibung des Ausgangspunkt: Auf meinem KVM-Server laufen mehrere virtuelle Maschinen, deren Datenträger sich in Logical Volumes befindet. Es gibt in den virtuellen Maschinen diverse Backup-Scripts für wirklich kritische Daten, aber hin und wieder hätte ich zusätzlich gerne ein vollständiges Backup des virtuellen Datenträgers. Im Prinzip geht das so:

lvcreate -s -L 2G -n vmname_snap /dev/vg0/vmname
dd if=/dev/vg0/vmname_snap bs=4M of=/backup/vmname.img
lvremove -f /dev/vg0/vmname_snap

Ich führe also einen LVM-Snapshot durch, lese dann das LV mit dd aus und speichere es als Image-Datei in einem Backup-Verzeichnis (oder übertrage es via ftp, scp etc. auf einen anderen Backup-Server, das ist hier nicht relevant).

Im Prinzip funktioniert das gut, aber die Backup-Dateien werden recht groß. Z.B. habe ich beim Einrichten einer virtuellen Maschine ein LV mit 40 GByte eingerichtet. Die virtuelle Maschine beansprucht davon aber erst 5 GByte. Da wäre es sinnlos, jedesmal eine 40 GByte große Backup-Datei zu erstellen, oder?

Nun gut, dann komprimieren wir das Backup eben:

dd if=/dev/vg0/vmname_snap bs=4M | gzip -c > /backup/vmname.img.gz

Haben Sie schon einmal versucht, 40 GByte mit gzip zu komprimieren? Das dauert (fast) ewig, die CPU wird heiß und Ihr Server, wenn er nicht gerade im Leerlauf läuft, reagiert plötzlich nur noch träge.

Und das führt nach einer kurzen Google-Suche und ein paar eigenen Experimenten zum Kommando lzop aus dem gleichnamigen Paket. lzop komprimiert nicht so toll wie gzip und Co., ist dafür aber unheimlich schnell. Das eigentliche Backup-Kommando sieht nun so aus:

dd if=/dev/vg0/vmname_snap bs=4M | lzop -c > /backup/vmname.img.lzo

Zumindest für meine Zwecke ist das optimal: Der KVM-Host reagiert auch dann noch zufriedenstellend, wenn gerade ein Backup läuft, der Platzbedarf des Backups ist OK, der Zeitaufwand ebenso.

Ein paar Benchmark-Ergebnisse

Bis ich zum obigen Backup-Kommando gekommen bin, habe ich ein paar Benchmark-Tests durchgeführt — allerdings nicht auf meinem Root-Server und KVM-Host, sondern auf einem lokalen PC mit einer sehr schnellen SSD (Samsung 830). Dort gibt es das LV /dev/vg830/lv3 mit einer Größe von 9,8 GByte. Es enthält eine virtuelle Maschine mit einer kleinen CentOS-Installation. Das Listing zeigt verschiedene Verfahren, das LV zu sichern.

time dd if=/dev/vg830/lv3 of=lv3.img bs=4M
  10485760000 Bytes (10 GB) kopiert, 51,1847 s, 205 MB/s
  real  0m51.425s
  user  0m0.000s
  sys   0m15.013s

du -h lv3.img
  9,8G  lv3.img

----------------

time dd if=/dev/vg830/lv3 bs=4M | gzip -c > lv3.img.gz
  10485760000 Bytes (10 GB) kopiert, 219,162 s, 47,8 MB/s
  real  3m39.172s
  user  3m15.036s
  sys   0m14.793s

du -h lv3.img.gz 
  1,4G  lv3.img.gz

----------------------

time dd if=/dev/vg830/lv3 -bs 4M | gzip -c -1 > lv3.img.gz
  10485760000 Bytes (10 GB) kopiert, 119,3 s, 87,9 MB/s
  real  1m59.306s
  user  1m33.010s
  sys   0m14.721s

du -h lv3.img.gz 
  1,6G  lv3.img.gz

----------------

time dd if=/dev/vg830/lv3 bs=4M | 7zr a -si lv3.img.7z
  10485760000 Bytes (10 GB) kopiert, 1493,4 s, 7,0 MB/s
  real  24m53.424s
  user  38m37.841s
  sys   0m30.446s

du -h lv3.img.7z 
  926M  lv3.img.7z

-------------------------

time dd if=/dev/vg830/lv3 bs=4M | lzop -c > lv3.img.lzo
  10485760000 Bytes (10 GB) kopiert, 63,8877 s, 164 MB/s
  real  1m4.631s
  user  0m29.930s
  sys   0m18.865s

du -h lv3.img.loz 
  2,1G  lv3.img.loz

Eine kurze Zusammenfassung: Am schnellsten ist das Backup mit einem simplen dd-Kommando erledigt (51 Sekunden). Allerdings ist der Platzbedarf hoch (9,8 GB).

gzip ohne weitere Parameter verkleinert das Backup auf 1,4 GB, die Ausführung dauert aber nun 3:39. Wird gzip mit der Option -1 angewiesen, lieber schnell und weniger gut zu komprimieren, steigt der Backup-Platzbedarf auf 1,6 GB, die Backup-Zeit sinkt auf zwei Minuten.

Dem Komprimierkommando 7zr (Paket p7zip) gelingt das Kunststück, das Backup auf 926 MByte zu schrumpfen. Das dauert dann aber 25 Minuten, wobei gleich zwei CPU-Cores zum Einsatz kommen. Daher ist die user-Zeit größer als die real-Zeit.

Mein persönlicher Favorit ist lzop: Die Backup-Zeit steigt gegenüber einem reinen dd-Kommando nur minimal an (von 51 auf 64 Sekunden). Der Platzbedarf des Backups beträgt nun 2,1 GB. Das ist deutlich mehr als mit gzip und 7zr, aber immer noch weniger als ein Viertel im Vergleich zur unkomprimierten Variante.

Wie für alle Benchmark-Tests gilt: Sie werden ganz andere Ergebnisse erzielen — je nachdem, wie gut sich Ihre Image-Dateien komprimieren lassen, wie schnell Ihre CPU ist, wie schnell die Festplatte oder SSD ist etc.

PS: In meinem realen KVM-Server befinden sich übrigens eine herkömmliche Festplatte und eine wesentlich langsamere CPU. Dort kommen die Vorteile von lzop noch stärker zum Tragen.

Update 14.5.2012

Ein Leser auf pro-linux.de hat vorgeschlagen, anstelle von dd einfach cat zu verwenden. Das spart nochmals ein paar Sekunden. Vielen Dank für den Hinweis!

time cat /dev/vg830/lv3 | lzop -c > lv3.img.lzo
  real  0m55.884s
  user  0m33.430s
  sys   0m19.717s