3 Punkte von GN⁺ 2026-01-03 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Analyse der Leistungsgrenzen von Bundler und Vergleich mit den Gründen, warum der Python-Paketmanager uv so schnell ist
  • Die Geschwindigkeit von uv beruht nicht auf Rust selbst, sondern auf strukturellen Designentscheidungen wie parallelen Downloads, globalem Cache und metadatenbasierter Abhängigkeitsverarbeitung
  • Bei Bundler sind Download und Installation gekoppelt, was die Parallelisierung einschränkt; eine Trennung verspricht deutliche Verbesserungen
  • Durch Integration eines globalen Caches, Installation per Hardlink und Einbindung des PubGrub-Solvers ließen sich Doppelungen zwischen RubyGems und Bundler reduzieren
  • Auch ohne Neuschreibung in einer anderen Sprache lassen sich die meisten Performance-Verbesserungen direkt in Ruby erreichen, sodass eine Geschwindigkeit nahe uv möglich ist

Leistungsvergleich von Bundler und uv

  • Ausgehend von der auf der RailsWorld gestellten Frage „Warum ist Bundler nicht so schnell wie uv?“ werden die Performance-Engpässe von Bundler untersucht
  • Der Autor ist überzeugt, dass Bundler Geschwindigkeiten auf uv-Niveau erreichen kann, und stellt klar, dass der Unterschied nicht an der Sprache, sondern am Design liegt
  • Unter Bezug auf Andrew Nesbitts Artikel „How uv got so fast“ wird analysiert, ob sich die zentralen Optimierungen von uv auf Bundler übertragen lassen

Neuschreibung in Rust?

  • Zwar ist uv in Rust geschrieben, doch die eigentliche Ursache für die Geschwindigkeit ist nicht Rust selbst
  • Wenn das Beseitigen der Engpässe in Bundler dazu führt, dass „eine Neuschreibung in Rust die einzig verbleibende Verbesserung“ wäre, dann wäre das bereits ein Erfolg
  • Eine Neuschreibung in Rust bietet die Freiheit, experimentelle Designs ohne bestehende Kompatibilitätszwänge auszuprobieren, ist aber keine zwingende Voraussetzung

Strukturelle Engpässe in Bundler

  • Bundler koppelt den Download und die Installation von Gems in einer einzigen Methode, wodurch parallele Downloads unmöglich werden
    • Im Beispielcode führt die Methode install nacheinander fetch_gem_if_not_cached und install aus
    • Dadurch können Gems mit Abhängigkeiten (a -> b -> c) nur sequentiell installiert werden
  • Experimente zeigen: Mit Abhängigkeiten dauert es über 9 Sekunden, während unabhängige Gems (d, e, f) per parallelem Download in weniger als 4 Sekunden abgeschlossen sind
  • Durch eine Trennung von Download und Installation ließe sich parallel arbeiten, ohne die Abhängigkeitsregeln zu verletzen
    • Vorgeschlagen wird eine Aufteilung in vier Schritte (Download → Entpacken → Kompilieren → Installation)
    • Bei reinen Ruby-Gems könnte die Installationsreihenfolge der Abhängigkeiten gelockert werden, was zusätzlichen Geschwindigkeitsschub bringen würde

Cache- und Installationsoptimierung

  • Das Modell von uv mit globalem Cache und Installation per Hardlink ließe sich auch auf Bundler anwenden
    • Bundler und RubyGems verwenden derzeit getrennte Caches je Ruby-Version
    • Erforderlich wäre eine Zusammenführung in einen gemeinsamen Cache auf Basis von $XDG_CACHE_HOME
    • Die Installation per Hardlink wäre nach einer solchen Cache-Zusammenführung möglich
  • Bundler nutzt bereits den Abhängigkeits-Solver PubGrub, während RubyGems weiterhin molinillo verwendet
    • Eine Vereinheitlichung der Solver beider Systeme ist zentral für den Abbau technischer Schulden

Übertragbarkeit Rust-bezogener Optimierungen

  • Zero-copy-Deserialisierung könnte teilweise auch beim YAML-Parsing in RubyGems angewendet werden
  • Der GVL (Global VM Lock) von Ruby schränkt Parallelisierung bei IO-lastigen Aufgaben nicht stark ein
    • IO- und ZLIB-Verarbeitung geben den GVL frei, sodass parallele Ausführung möglich ist
    • Beim Schreiben kleiner Dateien kann allerdings der Overhead der GVL-Verwaltung die Leistung mindern
    • An Verbesserungen innerhalb von Ruby wird bereits gearbeitet
  • Optimierung von Versionsvergleichen: uv kodiert Versionen als u64-Integer, um Vergleiche zu beschleunigen
    • Auch in Ruby ließe sich Gem::Version in eine integerbasierte Darstellung überführen, um die Solver-Performance zu verbessern
    • Entsprechende Refactoring-Versuche gab es bereits, wurden aber wegen Abwärtskompatibilitätsproblemen aufgeschoben

Fazit und weitere Pläne

  • Die Geschwindigkeit von uv beruht eher auf einem Design, das unnötige Arbeit vermeidet, als auf der Sprache selbst; Bundler kann in dieselbe Richtung verbessert werden
  • RubyGems und Bundler verfügen bereits über eine moderne Paketverwaltungsstruktur, sodass Geschwindigkeiten auf uv-Niveau realistisch sind
  • Die größte Herausforderung bleibt Legacy-Code und die Wahrung der Kompatibilität
  • Auch ohne Neuschreibung in Rust sind 99 % der Performance-Gewinne innerhalb des Ruby-Codes erreichbar; das verbleibende 1 % fällt kaum ins Gewicht
  • In einem Folgebeitrag sollen das tatsächliche Profiling von Bundler und RubyGems sowie die konkreten Ursachen der Engpässe behandelt werden

Noch keine Kommentare.

Noch keine Kommentare.