Améliorer les performances de Ruby : réécrire du C en Ruby
Comparaison des performances de Ruby
- Dans un dépôt récent de comparaison de langages, Ruby est plus rapide que R et Python, mais est classé comme le troisième langage le plus lent.
- Les benchmarks se composent de deux tests, « Loops » et « Fibonacci », qui mettent respectivement en avant les boucles et les conditions, ainsi que le coût des appels de fonction et les performances de la récursion.
Comparaison des performances entre Ruby et Node.js
- Sur un MacBook Pro M3, Ruby 3.3.6 prend 28 secondes pour l’exemple de boucle et 12 secondes pour l’exemple Fibonacci.
- Node.js prend environ 1 seconde pour chacun des deux exemples.
- Sur un MacBook Air M2, les performances de Ruby sont encore moins bonnes.
Signification des benchmarks
- Ces benchmarks n’ont peut-être pas une grande signification en pratique.
- Python a été classé comme le langage le plus lent, mais c’est pourtant le langage le plus utilisé sur GitHub.
- Un langage de programmation doit être efficace, mais son utilité et la productivité qu’il apporte sont plus importantes que ses performances.
Application de YJIT
- L’activation de YJIT améliore fortement les performances de Fibonacci.
- Sur l’exemple de boucle, le gain de performances reste minime.
Optimisation du code Ruby
Range#each est écrit en C, ce qui empêche toute optimisation par YJIT.
Integer#times a été converti du C vers Ruby dans Ruby 3.3, ce qui permet son optimisation par YJIT.
Array#each a été converti du C vers Ruby dans Ruby 3.4.
Optimisation de Integer#times
Integer#succ fonctionne plus rapidement que i += 1.
- YJIT optimise
Integer#times, ce qui améliore fortement les performances.
Optimisation de Array#each
Array#each a été converti du C vers Ruby dans Ruby 3.4, ce qui permet son optimisation par YJIT.
- Le module
Primitive est utilisé pour évaluer du code C depuis Ruby.
Dépôt Ruby Microbench
- Les benchmarks sont exécutés avec différentes versions de Ruby et avec YJIT.
- Ruby 3.4 avec YJIT montre une nette amélioration des performances.
Optimisation de range#each
- Il est possible d’améliorer les performances en implémentant la classe
Range en Ruby pur.
Bibliothèque standard YJIT
- L’équipe YJIT améliore les performances en remplaçant du code C par du Ruby.
- Le bloc
with_yjit permet d’utiliser l’implémentation Ruby lorsque YJIT est activé.
Analyse des optimisations de YJIT
- YJIT optimise les performances en convertissant le bytecode de la VM Ruby en code machine.
- L’analyse du code machine de
Integer#succ permet de comprendre le processus d’optimisation de YJIT.
1 commentaires
Commentaires Hacker News
L’exemple de boucle répète l’opération un milliard de fois et utilise des boucles imbriquées. On suppose que ce benchmark passera plus de 99 % de son temps sur les deux premières lignes
un’est pas connu à la compilation, la boucle interne pourrait être remplacée par quelques instructionsIl est fait mention des futures versions de Ruby : Ruby 3.4.0 devrait sortir à Noël cette année, et Ruby 3.5.0 au Noël suivant
J’ai toujours de l’affection pour Ruby. Merci à Matz
Il y a eu un PR d’amélioration des performances de
Integer#succau début de 2024, ce qui m’a permis de comprendre pourquoi on utiliseInteger#succInteger#succest utilisé lors de la réécriture de méthodes de boucle, et dans l’interpréteuropt_succ (i = i.succ)est traité plus rapidement queputobject 1; opt_plus (i += 1)#succpour la lisibilité, et je l’emploie deux fois dans la méthode#bytesd’une bibliothèque UUID pour conserver un « mode bit slicing » lors de la lecture du codePartage d’une expérience liée à TruffleRuby, qui serait plus rapide que Node.js et proche de Bun ou de Golang
Ruby est devenu très rapide, et TruffleRuby est encore plus impressionnant
Je ne savais pas que YJIT était écrit en Rust
Python était le langage le plus lent dans le benchmark, mais en octobre 2024 c’était aussi le langage le plus utilisé sur GitHub
Il existe un ancien dépôt de comparaison de langages incluant davantage de langages
Cela a profondément changé les solutions Advent of Code, et cela paraît étonnamment similaire