Le crate bzip2 passe de C à 100 % Rust
(trifectatech.org)- Le crate bzip2 remplace sa dépendance au code C par une implémentation 100 % Rust
- Les performances s’améliorent globalement par rapport à avant, et la cross-compilation devient plus simple
- L’implémentation Rust améliore à la fois la vitesse de compression et de décompression par rapport à la version C
- Les problèmes de dépendances de bibliothèques, comme les conflits de symboles, sont fortement réduits
- Après un audit de sécurité, un bug logique critique a été corrigé, ce qui a permis de valider la stabilité
Sortie de bzip2 crate 0.6.0 et transition vers Rust
- La version 0.6.0 de bzip2 a été publiée aujourd’hui
- Elle utilise désormais par défaut libbz2-rs-sys, une implémentation de l’algorithme bzip2 en Rust développée en interne
- Grâce à cette transition, le crate bzip2 est plus rapide et la cross-compilation est devenue plus simple
- Le crate libbz2-rs-sys peut aussi être compilé sous forme de bibliothèque dynamique C. Les projets C peuvent ainsi profiter eux aussi des gains de performance
Pourquoi cette transition ?
- L’algorithme bzip2 a été créé dans les années 90 et n’est plus très utilisé aujourd’hui, mais il reste nécessaire dans plusieurs protocoles et bibliothèques pour des raisons de conformité aux spécifications
- De nombreux projets dépendent de bzip2, non pas directement, mais quelque part en profondeur dans leur arbre de dépendances
- Forts de l’expérience accumulée avec zlib-rs, nous avons modernisé cette fois l’implémentation de bzip2
- Les détails d’implémentation de libbz2-rs-sys ont été abordés dans un précédent billet de blog. Ici, nous examinons les avantages de cette transition
Performances améliorées
- L’implémentation Rust affiche globalement de meilleures performances que la version C
- Dans certains cas, les performances sont équivalentes, mais elles ne sont jamais inférieures
- Performances de compression : bzip2 propose une option
level, mais son impact sur les performances reste limité - Les tests montrent que, sur des fichiers d’exemple représentatifs, la version Rust gagne plus de 10 % en vitesse
Compression :
| Fichier | C (cycles d’exécution) | Rust (cycles d’exécution) | Variation relative |
|---|---|---|---|
| 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% |
La décompression montre elle aussi des gains de performance dans tous les cas :
| Fichier | C (cycles d’exécution) | Rust (cycles d’exécution) | Variation relative |
|---|---|---|---|
| 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% |
En revanche, sur macOS, on observe parfois des variations dans les mesures de décompression. Les limites des outils de benchmark ont rendu l’analyse difficile
Support de la cross-compilation
- Dans les projets Rust avec dépendances C, la cross-compilation fonctionne généralement bien grâce au crate cc, mais lorsqu’elle échoue, le débogage est très difficile
- Des problèmes inattendus surviennent facilement lors de l’édition des liens avec des bibliothèques système, et cela devient un véritable obstacle dans certains environnements, notamment pour les builds WebAssembly
- Le passage à une implémentation Rust fait disparaître complètement les problèmes liés au C
- Il est désormais possible de cross-compiler vers Windows, Android, WebAssembly et d’autres cibles sans particularité notable
- C’est un avantage majeur non seulement pour l’expérience utilisateur, mais aussi pour la maintenance
Plus de conflits de symboles (export) par défaut
- Avec une dépendance C, il faut exporter des symboles depuis des blocs externes Rust, ce qui provoque des conflits si une autre dépendance exporte les mêmes symboles
- libbz2-rs-sys est conçu pour ne pas exporter de symboles par défaut
- Il n’y a donc pas de risque de conflit de symboles avec d’autres bibliothèques externes. Si besoin, l’export peut être activé via un feature flag
Exécution des tests avec MIRI
- Pour implémenter bzip2 efficacement en Rust, l’usage de code unsafe est inévitable, et la reproduction de l’interface C nécessite elle aussi beaucoup de code unsafe
- Heureusement, ce code peut être exécuté et testé dans l’environnement MIRI
- Mieux encore, les bibliothèques ou applications de plus haut niveau qui utilisent bzip2 peuvent désormais elles aussi être testées avec MIRI
Conclusion
Le crate bzip2 est désormais plus rapide. Sans même avoir à y penser, il offre naturellement une meilleure expérience
1 commentaires
Commentaires Hacker News
sudoécrit en Rust, ce type de remplacement paraît tout à fait plausible