Für ein zukünftiges Projekt würde ich gerne die Qualität von Kompressionsalgorithmen für das folgende Problem bewerten: Es sollen viele kleine Objekte mit pickle serialisiert und über ein Netzwerk übertragen werden. Die Objekte können sich in ihrer Größe unterscheiden, werden aber grundsätzlich nicht zu komplex. Auch ganze Warteschlangen, bestehend aus diesen Objekten sollen übertragen werden. Für die Vergleiche werden folgende Objekte zufällig generiert (als BNF notiert):

Objekt      = id, timestamp, {value}, description
id          = ? int64 ?
timestamp   = ? int32 ?
value       = float
description = {Character}
Character   = ? printable ascii characters ?

Als Kompressionsalgorithmen kommen zlib, zstd, lz4 und lzo in Frage. bz2 und lzma reduzieren den benötigten Platzbedarf zwar am meisten, sind aber auch erheblich langsamer als der Rest. Die benötigte Zeit ist das ausschlaggebende Kriterium. Da mich das Verhalten im Zusammenspiel mit Python3 interessiert wurden die Vergleiche auch mit Python3 (3.9.1) durchgeführt. Dabei wurden folgende externe Module verwendet:

Die Module zlib, bz2 und lzma sind teil der Standardbibliothek.

Kompression eines einzelnen Objektes

Die folgende Grafik zeigt die benötigte Zeit (Millisekunden), um ein Objekt einzeln und innerhalb einer Liste zu komprimieren.

single time

Hier wird die Größe in Byte nach der Kompression gezeigt. None ist die Größe der Quelldaten.

single bytes

Kompression von 100.000 Objekten

Nachfolgende Plots zeigen die aufsummierte Zeit und Datenmenge, wenn 100.000 Objekte einzeln komprimiert werden und zusammen als liste.

stream time

stream bytes

Dekompression der Objekte

Zum Schluss wird noch die benötigte Zeit für die Dekompression der Daten verglichen.

single decomp

stream decomp

Fazit

  1. Pickle arbeitet sehr schnell und legt die serialisierten Daten effizient ab. Wenn 100K Objekte in einer Liste verpackt werden, benötigen diese nur 1/3 des Speicherplatzes, als wenn jedes Objekt einzeln serialisiert wird.

  2. Einzelne Objekte (Events) zu komprimieren und sie im Anschluss zu übertragen scheint ineffizient zu sein, der eingesparte Speicherplatz für diese kleinen Objekte ist einfach zu gering. Bei größeren Objekten könnte eine Kompression wieder wieder sinnvoll sein. Man könnte größere Objekte soweit Komprimieren, dass sie in ein einzelnes TCP/UDP-Segment passen.

  3. zlib ist einfach zu langsam, auch mit dem niedrigstem Kompressionslevel (zlib_1). zstd eignet sich überhaupt nicht um kleine Datenmengen zu komprimieren, schneidet aber bei größeren Datenmengen hervorragend ab. zstd reduziert den benötigten Speicherplatz am besten, benötigt zur Kompression aber mehr Zeit als lzo und lz4, ist jedoch bei der Dekompression nur minimal langsamer als diese beiden sehr schnellen Algorithmen. zstd wäre damit der beste Kandidat um komplette Warteschlangen zu komprimiert zu übertragen.

  4. Soll eine Kompression von einzelnen Events erfolgen, ist lz4 der favorisierte Kandidat. Er komprimiert und dekomprimiert einfach am schnellsten.


Next post: Pandemieverlauf in Rostock

Previous post: LUCA-App: Geofencing ohne Funktion