3 points par GN⁺ 2026-01-03 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • Analyse des limites de performance de Bundler et comparaison avec les raisons de la rapidité de uv, le gestionnaire de paquets Python
  • La vitesse de uv ne vient pas du langage Rust, mais de choix d’architecture comme les téléchargements parallèles, le cache global et le traitement des dépendances basé sur les métadonnées
  • Bundler couple les phases de téléchargement et d’installation, ce qui limite le traitement parallèle, mais les séparer permettrait de nets progrès
  • Intégration d’un cache global, installation par liens physiques, intégration du solveur PubGrub : autant de pistes pour réduire les doublons entre RubyGems et Bundler
  • Même sans réécrire l’outil dans un autre langage, l’essentiel des gains de performance peut être obtenu en Ruby, avec un niveau de vitesse proche de celui de uv

Comparaison des performances entre Bundler et uv

  • L’enquête sur les goulots d’étranglement de Bundler part d’une question posée à RailsWorld : « Pourquoi Bundler n’est-il pas aussi rapide que uv ? »
  • L’auteur affirme être convaincu que Bundler peut atteindre un niveau de performance comparable à celui de uv, et souligne que l’écart vient de la conception, pas du langage
  • En s’appuyant sur l’article d’Andrew Nesbitt, “How uv got so fast”, il examine dans quelle mesure les optimisations clés de uv pourraient être appliquées à Bundler

Faut-il le réécrire en Rust ?

  • uv est bien écrit en Rust, mais la cause fondamentale de sa rapidité n’est pas Rust lui-même
  • Si l’on parvient à supprimer les goulots d’étranglement de Bundler au point que « le réécrire en Rust » devienne la seule amélioration restante, alors ce sera déjà une réussite
  • Une réécriture en Rust offrirait la liberté d’expérimenter une nouvelle conception sans les contraintes de compatibilité existantes, mais ce n’est pas une condition indispensable

Les goulots d’étranglement structurels de Bundler

  • Bundler combine le téléchargement et l’installation des gems dans une seule méthode, ce qui empêche les téléchargements parallèles
    • Dans l’exemple de code, la méthode install exécute successivement fetch_gem_if_not_cached puis install
    • En conséquence, des gems ayant des dépendances (a -> b -> c) ne peuvent être installées que de façon séquentielle
  • Les expérimentations montrent qu’en présence de dépendances, l’opération prend plus de 9 secondes, alors que des gems indépendantes (d, e, f) sont téléchargées en parallèle et terminées en moins de 4 secondes
  • Séparer téléchargement et installation permettrait de respecter les règles de dépendances tout en autorisant le parallélisme
    • Proposition de découpage en quatre étapes : téléchargement → décompression → compilation → installation
    • Pour les gems Ruby purs, on pourrait aussi assouplir l’ordre d’installation des dépendances pour gagner encore en vitesse

Optimisation du cache et de l’installation

  • Le modèle de cache global et d’installation par liens physiques de uv pourrait aussi être appliqué à Bundler
    • Aujourd’hui, Bundler et RubyGems utilisent des caches séparés selon les versions de Ruby
    • Une unification vers un cache partagé basé sur $XDG_CACHE_HOME est nécessaire
    • L’installation par liens physiques pourrait être introduite après cette unification du cache
  • Bundler utilise déjà le solveur de dépendances PubGrub, mais RubyGems s’appuie encore sur molinillo
    • L’unification des solveurs des deux systèmes est présentée comme la clé pour résorber cette dette technique

Applicabilité des optimisations liées à Rust

  • La désérialisation zero-copy pourrait être partiellement applicable à l’étape de parsing YAML de RubyGems
  • Le GVL (Global VM Lock) de Ruby n’est pas un obstacle majeur pour les tâches orientées IO
    • Les opérations d’IO et de ZLIB libèrent le GVL, ce qui permet une exécution parallèle
    • En revanche, l’écriture de petits fichiers subit le surcoût de gestion du GVL, ce qui pénalise les performances
    • Des travaux sont en cours dans Ruby pour améliorer ce point
  • Optimisation de la comparaison de versions : uv encode les versions sous forme d’entiers u64 pour accélérer les comparaisons
    • En Ruby aussi, convertir Gem::Version vers une représentation entière pourrait améliorer les performances du solveur
    • Une tentative de refactorisation a déjà existé, mais a été mise en pause pour des raisons de compatibilité descendante

Conclusion et suite

  • La rapidité de uv vient moins du langage que d’une conception qui élimine le travail inutile, et Bundler peut progresser dans la même direction
  • RubyGems et Bundler disposent déjà d’une architecture moderne de gestion des paquets, ce qui rend réaliste l’objectif d’atteindre des performances proches de uv
  • Le principal défi reste la compatibilité avec le code legacy
  • Même sans réécriture en Rust, 99 % des gains de performance sont possibles directement en Ruby, le 1 % restant étant marginal
  • Un prochain article abordera le profilage réel de Bundler et RubyGems ainsi que les causes concrètes des goulots d’étranglement

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.