Le crate bzip2 passe à une implémentation 100 % Rust au lieu du C
(trifectatech.org)- Le crate
bzip20.6.0 adopte par défautlibbz2-rs-sys, une implémentation Rust de l’algorithme bzip2, supprimant la dépendance au C tout en améliorant la vitesse et la facilité de compilation croisée - bzip2 est un ancien algorithme de moins en moins utilisé, mais de nombreux protocoles et bibliothèques doivent encore le prendre en charge pour respecter leurs spécifications, si bien qu’il reste présent au fond des arbres de dépendances
- L’implémentation Rust utilise environ 9,66 à 14,87 % de cycles CPU en moins que le C pour la compression, et améliore aussi la décompression sur l’ensemble des tests de 4,48 à 10,00 %
- La suppression du C simplifie les builds WebAssembly, Windows et Android, et comme les symboles
libbz2-rs-sysne sont pas exportés par défaut, le risque de conflits de symboles avec d’autres dépendances diminue également - L’audit a permis de corriger un bug logique off-by-one et certaines limites du fuzzer ; les bibliothèques et applications de plus haut niveau utilisant
bzip2peuvent désormais aussi être exécutées avec MIRI
Changement d’implémentation par défaut dans bzip2 0.6.0
- Le crate
bzip20.6.0 utilise par défautlibbz2-rs-sys, une implémentation Rust de l’algorithme bzip2 - En supprimant l’ancienne dépendance au C, le crate
bzip2devient plus rapide et plus facile à compiler en cross-compilation - Le crate
libbz2-rs-syspeut être compilé comme bibliothèque dynamique C, afin que les projets C puissent eux aussi profiter de ces améliorations - bzip2 est aujourd’hui peu utilisé, mais de nombreux protocoles et bibliothèques doivent encore le prendre en charge pour respecter leurs spécifications, et il reste profondément enfoui dans les arbres de dépendances de nombreux projets
- Les détails d’implémentation sont disponibles dans l’article précédent Translating bzip2 with c2rust
Résultats des améliorations de performances
- L’implémentation Rust est généralement plus rapide que l’implémentation C, et dans certains cas atteint un niveau de performance comparable au C
- Dans les plages connues, il n’existe aucun cas significativement plus lent
- Les benchmarks de compression montrent une baisse des cycles CPU par rapport au C
sample3.reflevel 1 :38.51M→33.53M, -14,87 %silesia-small.tarlevel 1 :3.43G→3.00G, -14,30 %silesia-small.tarlevel 9 :3.47G→3.17G, -9,66 %- Dans bzip2, le
leveldésigne la quantité de mémoire de travail utilisée et n’a pas d’impact majeur sur les performances sample3.refalloue déjà plus de mémoire que la taille du fichier avec le level 1, les levels plus élevés sont donc peu pertinents
- Les performances de décompression s’améliorent également sur l’ensemble des tests
sample3.bz2: -4,48 %sample1.bz2: -8,63 %sample2.bz2: -7,67 %dancing-color.ps.bz2: -5,17 %re2-exhaustive.txt.bz2: -7,65 %zip64support.tar.bz2: -10,00 %
- Sur la machine de benchmark macOS, les chiffres de performance en décompression ressortent parfois plus faibles
- La cause n’a pas été identifiée, et il a été difficile de faire fonctionner sous macOS des outils capables d’automatiser le suivi des performances comme
perf
- La cause n’a pas été identifiée, et il a été difficile de faire fonctionner sous macOS des outils capables d’automatiser le suivi des performances comme
Builds et réduction des conflits de symboles
- La compilation croisée de projets Rust ayant des dépendances C fonctionne souvent directement grâce au crate
cc, mais lorsqu’elle échoue, le débogage des erreurs peut être difficile- L’édition de liens avec des bibliothèques système peut aussi créer des problèmes confus et difficiles à reproduire
- La compilation WebAssembly de bzip2 posait problème depuis longtemps
- En supprimant la dépendance C et en n’utilisant que du code Rust, les builds WebAssembly, Windows et Android deviennent plus faciles à faire fonctionner
libbz2-rs-sysn’exporte pas de symboles par défaut- Avec une dépendance C, il faut exporter les symboles pour que les blocs Rust
externpuissent les trouver - Les noms exportés peuvent entrer en conflit lorsqu’une autre dépendance déclare les mêmes symboles
- Si un projet Rust a besoin d’exporter des symboles, il peut l’activer via un feature flag
- Avec une dépendance C, il faut exporter les symboles pour que les blocs Rust
Validation et résultats de l’audit
- Une implémentation performante de bzip2 nécessite une partie de code unsafe, et reproduire l’interface C en Rust demande encore davantage de code unsafe
- Ce code peut être exécuté avec MIRI
- Les bibliothèques de plus haut niveau ou les applications utilisant
bzip2peuvent désormais aussi être exécutées avec MIRI
- L’audit a découvert un bug logique off-by-one et corrigé certaines limites du fuzzer
- Aucun autre élément important n’a été relevé
- L’audit a été réalisé par Radically Open Security, et le rapport complet est disponible dans le rapport d’audit PDF
- Ce travail a bénéficié de l’aide d’Alex Crichton, mainteneur du crate
bzip2, de Radically Open Security pour l’audit et son expertise, ainsi que de la NLnet Foundation, qui a financé le projet via l’e-Commons Fund
Aucun commentaire pour le moment.