Datentompression um das Vierfache beschleunigen, ohne Code umzuschreiben
Warum etwas ändern, das seit den Neunzigern funktioniert
Die originale zlib-Bibliothek erschien vor dreißig Jahren. Mark Adler und Jean-Loup Gailly schufen ein unglaublich zuverlässiges und portables Werkzeug. Es funktioniert nahezu überall, von Smartwatches bis hin zu Legacy-Betriebssystemen. Doch diese Universalität hat einen Nachteil.
Um die Kompatibilität mit alten Compilern und 16-Bit-Umgebungen zu gewährleisten, schleppt der zlib-Code eine Reihe von Workarounds mit sich. Er ist voll von Speicherlimit-Prüfungen und Makros zur Unterstützung archaischer Prozessoren. Aus diesem Grund konnten frische Optimierungen für Vektorinstruktionen von modernen Entwicklern schlicht nicht in das Haupt-Repository eingepflegt werden. Mark Adler pflegt einen hohen Stabilitätsanspruch, und sein Vorgehen ist nachvollziehbar.
Genau hier entschloss sich Hans Christian Rosbach (Dead2), die akkumulierten Community-Patches in einem einzigen Fork zusammenzuführen. So entstand das zlib-ng-Projekt.
Was sich in zlib-ng geändert hat
Die Idee des Forks ist einfach: den alten Legacy-Code ablegen und Vektorinstruktionen moderner CPUs anwenden. Entwickler nahmen Patches von Intel und Cloudflare, bereinigten die Beispiele aus den Neunzigern und schrieben zentrale Algorithmen in C11 neu.
Die Ergebnisse waren greifbar. Auf der x86-64-Architektur funktionieren Komprimierung und Dekomprimierung ungefähr viermal schneller als bei Standard-zlib.
Was diese Leistungssteigerung antreibt:
- Vektorinstruktionen für verschiedene Architekturen. AVX2, AVX-512, SSSE3 für x86, NEON für ARM, sowie Vektoreinheiten für POWER, RISC-V, LoongArch und IBM Z werden genutzt.
- Automatische CPU-Fähigkeitserkennung zur Laufzeit. Die kompilierte Binärdatei weiß selbst, welche vektorisierten Funktionen auf einem bestimmten Prozessor aufgerufen werden müssen.
- Schnelle Deflate-Algorithmen. Intels Arbeit an der Optimierung der Wiederholungssuche, Hash-Verschiebung und CRC32-Berechnung wird verwendet.
- Sicherer unaligned Zugriff. Lesen und Schreiben von unaligned Memory wird zusammen mit einem aktualisierten Bit-Buffer optimiert.
Gleichzeitig versucht das Projekt nicht, die bestehende Welt zu zerbrechen. Die Bibliothek kann mit einer API gebaut werden, die vollständig kompatibel mit Standard-zlib ist, oder man verwendet die eigene aktualisierte native API.
Wie man es selbst baut und ausprobiert
Das Projekt verfügt über zwei Build-Systeme: CMake und das gute alte configure.
Bei Verwendung von CMake sieht der Build vertraut aus:
Der Parameter aktiviert den vollständigen Kompatibilitätsmodus mit dem klassischen zlib. Die Ausgabe ist eine Bibliothek, die das System- ersetzen kann.
Für Fans des vertrauten -Build-Prozesses sieht es nicht anders aus:
Wenn man den vcpkg-Abhängigkeitsmanager verwendet, muss man die Quellen überhaupt nicht manuell herunterladen:
Anwendungen mit LD_PRELOAD beschleunigen
Einer der interessantesten Tricks mit zlib-ng ist das Beschleunigen bestehender Software, ohne deren Code zu ändern. Wenn Ihr Programm dynamisch mit verlinkt ist, können Sie die Bibliothek zur Laufzeit ersetzen.
So starten Sie ein Utility mit einer temporären Substitution:
Die Anwendung nutzt sofort die Vektorinstruktionen Ihres Prozessors, ohne jegliche Änderungen an der Binärdatei.
Allerdings warnen die Autoren des Forks ausdrücklich in der README: Versuchen Sie nicht, das System- auf Distributionsebene in Linux--Verzeichnissen zu ersetzen. Wenn etwas schiefgeht oder eine seltene Inkompatibilität auftritt, stürzt das gesamte System ab, einschließlich der Systemdienste. Es ist sicherer, den Fork in einem separaten Verzeichnis wie zu installieren und ihn explizit zu verlinken.
Wie gut ist der Code durch Tests abgedeckt
Code, der für Datenkomprimierung verantwortlich ist, muss ohne Ausfälle funktionieren. Selbst ein einziges verlorenes Bit macht ein Archiv zu Müll. Die zlib-ng-Autoren nehmen das Testen ernst.
Im Repository kommt ein umfassender Satz an Prüfungen zum Einsatz:
- Memory Sanitizer und Fuzzing über OSS-Fuzz.
- Native und emulierte CI über QEMU für ARM, PowerPC, RISC-V, SPARC64 und S390x.
- Unit-Tests basierend auf Google Test.
- Leistungsmessungen mit Google Benchmark.
Dank kontinuierlichem Fuzzing pflegt die Bibliothek ein hohes Zuverlässigkeitsniveau, was kritisch ist, wenn man Kernkomponenten des Systems ersetzt.
Wer wird von zlib-ng profitieren
Allen voran wird der Fork für Teams nützlich sein, bei denen Komprimierung und Dekomprimierung von Daten zum Flaschenhals geworden sind. Wenn Sie Gigabytes an Logs verarbeiten, mit Webservern wie nginx arbeiten, Texturen in der Spieleentwicklung komprimieren oder enorme Datenmengen im Backend verarbeiten, wird zlib-ng einen spürbaren Geschwindigkeitsschub liefern.
Andererseits macht es keinen Sinn, das bewährte originale zlib anzufassen, wenn Ihre Software auf alten 16-Bit-Mikrocontrollern oder völlig exotischen, drei Jahrzehnte alten Betriebssystemen läuft. Der Fork wurde spezifisch für moderne Plattformen geschaffen.
Das Werkzeug wirkt ausgereift und wird aktiv von der Community gepflegt. Wenn Sie maximale DEFLATE- und gzip-Leistung auf moderner Hardware benötigen, lohnt es sich, ein paar Stunden zu investieren und Benchmarks mit Ihren Daten durchzuführen.
Ähnliche Projekte