3 Punkte von GN⁺ 2025-06-19 | 1 Kommentare | Auf WhatsApp teilen
  • Die bzip2-Crate ersetzt ihre C-Code-Abhängigkeit vollständig durch eine 100%ige Rust-Implementierung
  • Die Leistung verbessert sich insgesamt gegenüber bisher, und Cross-Compilation wird einfacher
  • Die Rust-Implementierung verbessert sowohl die Datenkompression als auch die Dekompressionsgeschwindigkeit gegenüber der C-Version
  • Probleme mit Bibliotheksabhängigkeiten wie Symbolkonflikte werden deutlich reduziert
  • Nach einem Sicherheitsaudit wurden wichtige Logikfehler behoben und die Stabilität verifiziert

Veröffentlichung von bzip2 Crate 0.6.0 und Umstellung auf Rust-Basis

  • Heute wurde bzip2 Version 0.6.0 veröffentlicht
  • Standardmäßig wird nun die eigens entwickelte Rust-basierte Implementierung des bzip2-Algorithmus libbz2-rs-sys verwendet
  • Durch diese Umstellung wird die bzip2-Crate schneller, und Cross-Compilation wird einfacher
  • Die Crate libbz2-rs-sys kann auch als C-Dynamic-Library gebaut werden. Dadurch können auch C-Projekte von den Leistungsverbesserungen profitieren

Warum wurde diese Umstellung vorgenommen?

  • Der bzip2-Algorithmus wurde in den 90er-Jahren entwickelt und wird heute nicht mehr besonders häufig verwendet, ist aber in verschiedenen Protokollen und Bibliotheken weiterhin für Spezifikationskonformität nötig
  • Viele Projekte hängen nicht direkt, aber irgendwo tief im Abhängigkeitsbaum, von bzip2 ab
  • Auf Basis der Erfahrungen aus zlib-rs wurde diesmal die bzip2-Implementierung modernisiert
  • Details zur Implementierung von libbz2-rs-sys wurden in einem früheren Blogbeitrag behandelt. Hier geht es um die Vorteile dieser Umstellung

Verbesserte Leistung

  • Die Rust-Implementierung zeigt insgesamt eine höhere Leistung als die C-Version
  • In manchen Situationen ist die Leistung gleichwertig, aber es gibt keine Fälle, in denen sie langsamer ist
  • Kompressionsleistung: bzip2 bietet zwar eine Level-Option, deren Einfluss auf die Leistung ist jedoch gering
  • In Tests zeigte die Rust-Version bei repräsentativen Beispieldateien eine Geschwindigkeitssteigerung von mehr als 10%

Kompression:

Datei C(Ausführungszyklen) Rust(Ausführungszyklen) Relative Veränderung
sample3.ref (level 1) 38.51M 33.53M -14.87%
silesia-small.tar (level 1) 3.43G 3.00G -14.30%
silesia-small.tar (level 9) 3.47G 3.17G -9.66%

Auch bei der Dekompression wurde in allen Fällen eine verbesserte Leistung erzielt:

Datei C(Ausführungszyklen) Rust(Ausführungszyklen) Relative Veränderung
sample3.bz2 2.53M 2.42M -4.48%
sample1.bz2 9.63M 8.86M -8.63%
sample2.bz2 20.47M 19.02M -7.67%
dancing-color.ps.bz2 87.46M 83.16M -5.17%
re2-exhaustive.txt.bz2 1.89G 1.76G -7.65%
zip64support.tar.bz2 2.32G 2.11G -10.00%

Allerdings ändern sich die Dekompressionswerte unter macOS gelegentlich. Wegen der Grenzen der Performance-Messwerkzeuge war eine genaue Analyse schwierig

Unterstützung für Cross-Compilation

  • Die Cross-Compilation von Rust-Projekten mit C-Abhängigkeiten funktioniert dank der cc-Crate normalerweise gut, aber wenn sie fehlschlägt, ist das Debugging sehr schwierig
  • Beim Linken von Systembibliotheken treten leicht unerwartete Probleme auf, und in einigen Umgebungen, darunter WebAssembly-Builds, wird das zu einem praktischen Hindernis
  • Durch die Umstellung auf die Rust-Implementierung verschwinden C-bezogene Probleme vollständig
  • Cross-Compilation ist nun auch für Windows, Android, WebAssembly und weitere Ziele ohne besondere Auffälligkeiten möglich
  • Das ist nicht nur für die User Experience, sondern auch aus Wartungssicht ein großer Vorteil

Standardmäßig keine Symbol-Export-Konflikte

  • Bei C-Abhängigkeiten müssen Symbole in externen Rust-Blöcken exportiert werden; wenn andere Abhängigkeiten dieselben Symbole exportieren, entstehen Konflikte
  • libbz2-rs-sys ist so entworfen, dass standardmäßig keine Symbole exportiert werden
  • Deshalb kommt es nicht zu Symbolkonflikten mit anderen externen Bibliotheken. Falls nötig, kann der Export per Feature-Flag aktiviert werden

MIRI-basierte Tests

  • Um bzip2 in Rust performant zu implementieren, ist der Einsatz von unsafe Code unvermeidlich, und auch für die Nachbildung der C-Schnittstelle ist viel unsafe Code nötig
  • Glücklicherweise lässt sich dieser Code in einer MIRI-Umgebung ausführen und testen
  • Darüber hinaus können jetzt auch höher liegende Bibliotheken oder Anwendungen, die bzip2 verwenden, mit MIRI getestet werden

Fazit

Die bzip2-Crate ist jetzt schneller und bietet ganz selbstverständlich eine bessere Erfahrung, ohne dass man sich weiter darum kümmern muss

1 Kommentare

 
GN⁺ 2025-06-19
Hacker-News-Kommentare
  • Wenn man bedenkt, dass die Implementierung von Trifecta Tech möglicherweise die offizielle Implementierung ersetzen könnte, die von Linux-Distributionen verwendet wird, scheint das nicht unmöglich, zumal Fedora früher bereits das bisherige Adler zlib durch zlib-ng ersetzt hat. Der entscheidende Punkt sei, eine zum Original kompatible C-ABI bereitzustellen.
    • Falls es seit 2019 keine Upstream-Releases mehr gegeben habe, stelle sich die Frage, ob diese Implementierung nicht einfach bereits fertig sei. Wenn es keine Bugs mehr zu beheben und keine Funktionen mehr hinzuzufügen gebe, sei das an sich ausreichend.
    • Da Ubuntu ein in Rust geschriebenes sudo verwende, erscheine ein solcher Austausch durchaus realistisch.
    • Trifecta Tech stelle die C-ABI zwar bereits gut und kompatibel bereit, aber letztlich müsse jemand diese Umstellung auch tatsächlich durchführen, damit sich etwas ändere.
    • Es wird erwähnt, dass auch uutils auf einen solchen offiziellen Ersatz abzielt, und ein Link zur uutils-Website wird geteilt.
    • Bei einem kurzen Blick wirke es bereits positiv, dass eine cargo-c-Konfiguration vorhanden sei, aber wegen des anderen Namespace werde ein bestehendes C-Programm die Bibliothek nicht automatisch als bisheriges libbz2 erkennen. Da keine Vertrautheit mit den bzip2-Symbolen bestehe, sei schwer zu sagen, ob die ABI tatsächlich exakt kompatibel sei. Die direkte Pflege einer GNU-Betriebssystemimplementierung sei sehr zeitaufwendig und daher schwierig; Pull Requests für das experimentelle Projekt platypos seien willkommen, falls jemand Zeit habe.
  • Ich verwende dieses Crate, um Hunderte von TB an Common-Crawl-Daten zu verarbeiten. Ich bin sehr zufrieden, weil es schneller geworden ist.
    • Es wird gefragt, warum hier bz2 verwendet wird. Wenn man eine große Umwandlung nur einmal durchführen müsse, habe man gehört, dass ein Wechsel zu zstd große Vorteile bringe, und bei höherer Kompression sei es bzip2 in jeder Hinsicht überlegen.
    • Es wird gefragt, ob Common-Crawl-Daten als Torrents veröffentlicht werden.
    • Eine um 14 % schnellere Kompression wird als ziemlich beeindruckend bezeichnet.
  • Es wird gefragt, ob diese Implementierung die standardmäßig noch offenen 11 CVEs behebt. Ironischerweise habe es auch für das bzip2-Crate CVE-Meldungen gegeben; dazu wird ein entsprechender Link geteilt.
    • Es wird angemerkt, dass der Kontrast interessant sei zwischen den für dieses Crate gemeldeten Schwachstellen der Art „Laufzeitfehler bei großen Dateien“ und den „bounds miss“-Problemen in der C-Version. Es wird gefragt, ob solche bounds-miss-Schwachstellen tatsächlich bis zur Codeausführung führen könnten.
    • Zitiert wird der Hinweis, dass „das bzip2-Crate in Versionen vor 0.4.4 verwundbar ist“. Ergänzend wird erwähnt, dass heute 0.6.0 veröffentlicht wurde.
  • Auf die Frage, warum man einen Algorithmus aus den 90ern überhaupt noch verbessere, äußert jemand Neugier, welche Algorithmen heute stattdessen verwendet werden. zstd wird erwähnt und ein Benchmark-Vergleich von Kompressionsalgorithmen wird per Link geteilt.
  • Es wird gefragt, wie die Geschwindigkeitssteigerung zustande kommt, wenn C und Rust bei der Compiler-Codegenerierung doch denselben Backend-Codegen verwenden. Als mögliche Faktoren werden Rusts Auto-SIMD, direkte Optimierungen oder die Nutzung neuer Optimierungsbibliotheken genannt.
    • Eine Vermutung ist, dass Rust dem Codegenerator mehr Hinweise geben könne. Als Beispiel wird genannt, dass man sich im Unterschied zu C-Zeigern weniger Sorgen um Aliasing-Probleme machen müsse. Dazu wird ein Link zur Erklärung von Aliasing geteilt.
    • Es wird die Meinung geäußert, dass C für das Schreiben moderner Hochleistungscode wirklich ungeeignet sei. Von C99 bis C21 habe der Sprache über rund 20 Jahre hinweg die Möglichkeit gefehlt, neue Instruktionen wie clz, popcnt, clmul oder pdep auf saubere Weise zu nutzen. Schon die Unterstützung solcher abstrakten Instruktionszugriffe helfe bei Optimierungen dieser Art erheblich.
    • Es wird darauf hingewiesen, dass eine Neuschreibung in jeder Sprache Chancen auf Geschwindigkeitsgewinne bietet und Rust keine einzigartige Geschwindigkeitsgarantie mitbringt.
  • Es wird die Hoffnung geäußert, dass Nana oder Prossimo auf ähnliche Weise auch Kernprotokolle des Internets (BGP, OSPF, RIP usw.), Routing-Implementierungen und DNS-Server neu schreiben.
    • Es werden Fonds vorgestellt, die in den letzten Jahren Umschreibungen zentraler Internet- und OS-Werkzeuge in Rust oder anderen sicheren Sprachen unterstützt haben, darunter das NLnet-Projekt und der Sovereign Tech Fund. Als Beispiel wird auch das BGP-in-Rust-Projekt erwähnt.
    • Die Memory Safety Initiative stelle Bemühungen für sichere Neuschreibungen zentraler Dienste wie TLS und DNS vor und passe damit teilweise zum genannten Vorschlag.
    • Es wird erwähnt, dass ein Entwickler Ironsides DNS in SPARK Ada geschrieben habe; diese Sprache unterstütze stärkere formale Beweise.
  • Es wird die Ansicht geäußert, dass man auf macOS auch ohne den perf-Profiler mit dtrace eine ausreichende Leistungsanalyse durchführen könne. Das ursprüngliche flame graph-Skript in Perl habe ebenfalls dtrace verwendet, und auch die in Rust neu implementierte Version nutze denselben Ansatz. Einige Metriken wie Cache-Misses oder micro instruction retired fehlten zwar, dennoch sei es sehr nützlich.
  • Ein scherzhafter Kommentar meint, Rust müsse als Nächstes in Javascript neu geschrieben werden.
  • Es wird gefragt, ob wie bei lbzip2 parallele Dekompression unterstützt wird, etwa über ein Vorab-Scannen von Block-Magic zur Parallelverarbeitung. In einer nachträglichen Bearbeitung lautet das Fazit: vermutlich nicht.
  • Es wird geschildert, dass Lbzip2 durch die Nutzung aller CPU-Kerne sehr schnelle Dekompression ermöglicht habe. Obwohl inzwischen 2025 sei, nutzten viele wichtige Programme wie Python immer noch nur einen Kern, was bedauert wird.
    • Es wird eingewandt, dass diese Einschätzung zu Python nicht gut verstanden sei.