Les nombreux interprètes et runtimes du langage de programmation Ruby
Publié: 2022-03-11introduction
Tout comme il existe de nombreuses nuances de la gemme ruby, il existe plusieurs implémentations de l'interpréteur Ruby.
L'interpréteur Ruby le plus couramment utilisé est l'implémentation de référence, Ruby MRI, développée en C par le créateur de Ruby (Yukihiro Matsumoto) et l'équipe principale de Ruby.
Notre guide de recrutement Ruby on Rails mentionne que certains des inconvénients de Rails peuvent potentiellement être résolus ou évités en utilisant un autre interpréteur Ruby. Cet article présente les différentes implémentations et runtimes d'interpréteur Ruby existants disponibles aujourd'hui, en discutant des avantages et des inconvénients de chacun.
Historique des versions de Ruby (et comment cela affecte les implémentations alternatives)
Malheureusement, il n'y a pas d'équivalent de Python Language Reference pour Ruby (ISO/IEC 30170:2012 décrit Ruby 1.8 / Ruby 1.9, mais aucune spécification correspondante n'existe pour Ruby 2.x). En l'absence d'une telle spécification de langage, les implémenteurs Ruby s'appuient généralement sur la RubySpec pilotée par la communauté qui spécifie les comportements attendus du langage Ruby via des tests pouvant être exécutés dans n'importe quel interpréteur Ruby. RubySpec est donc utilisé par les implémenteurs Ruby pour vérifier la conformité comportementale de leurs implémentations Ruby avec la norme de facto.
En raison de l'absence de spécification formelle, les nouvelles versions de Ruby correspondent souvent simplement aux nouvelles versions du Ruby MRI. Il convient de noter qu'il existe un problème ouvert qui traite d'un processus de conception pour découpler Ruby (le langage) de Ruby MRI.
Cependant, étant donné le couplage étroit actuel entre le langage Ruby et l'implémentation de référence MRI, les développeurs d'implémentations Ruby alternatives ont parfois du mal à suivre les changements de langage introduits dans chaque nouvelle version MRI.
Cela n'a jamais été aussi difficile que lors de la transition entre Ruby 1.8 et Ruby 1.9. En 2007, dans un effort pour nettoyer et consolider la syntaxe de Ruby (le langage ayant évolué au cours de la décennie depuis la sortie de Ruby 1.0), l'équipe principale de Ruby a publié Ruby 1.9.0, une version qui a introduit de nombreuses incompatibilités rétroactives dans le langage. . En conséquence, toutes les implémentations Ruby n'ont pas investi l'effort nécessaire pour faire le saut syntaxique de 1.8 à 1.9. En tant que tel, il existe plusieurs implémentations Ruby basées sur 1.8 qui ne sont plus utilisées par la communauté, mais que vous pouvez toujours trouver en ligne ou dont les anciens de Ruby parlent.
Une nouvelle version de Ruby MRI sort chaque Noël, suivant un principe de versioning sémantique. Ruby 2.0 (publié en 2013) et 2.1 (publié en 2014) ont chacun introduit des fonctionnalités de langage supplémentaires dont les développeurs Ruby peuvent tirer parti, sans renoncer à la rétrocompatibilité avec Ruby 1.9.
Pourquoi utiliser une implémentation Ruby alternative ? Quel est le problème avec l'IRM ?
Il existe une variété d'implémentations Ruby alternatives, prenant en charge un large éventail de cas d'utilisation et d'environnements. Environnements Java Entreprise. Applications mobiles. Implémentations JavaScript. Machines à faible CPU/RAM. En plus de prendre en charge ces cas d'utilisation, des implémentations alternatives peuvent parfois également offrir une augmentation supplémentaire de la vitesse ou une utilisation plus efficace de la mémoire, selon les caractéristiques de votre application.
Pendant longtemps, de nombreux développeurs Ruby on Rails ont utilisé Ruby Enterprise Edition (REE) au lieu de MRI, profitant des meilleures techniques de gestion de la mémoire dans REE par rapport à la version MRI de l'époque. (REE a ensuite été abandonné en 2012.)
Bien que l'IRM soit l'implémentation par défaut de Ruby, ce n'est pas nécessairement le bon choix pour tous les environnements et scénarios. Par exemple, le support de la simultanéité de MRI est inférieur à celui de JRuby ou Rubinius. De plus, bien que les schémas de mémoire et de récupération de place de MRI s'améliorent constamment, ils ont encore quelques problèmes.
L'étude des implémentations Ruby qui suit est destinée à vous aider à sélectionner l'interpréteur le mieux adapté aux objectifs et contraintes opérationnels de votre projet.
Matz's Ruby Interpreter (MRI) / CRuby
Écrit en C par l'équipe principale de Ruby dirigée par Yukihiro Matsumoto ("Matz", le créateur de Ruby), MRI est l'implémentation de référence de Ruby qui sert de standard de facto. Si un fournisseur de système d'exploitation inclut une version de Ruby dans le cadre du logiciel installé sur le système d'exploitation, par exemple, il s'agit généralement de la version MRI. MRI bénéficie de plus de membres de l'équipe principale rémunérés que toute autre implémentation Ruby, ainsi que de ressources dédiées fournies par des personnes ou des entreprises qui souhaitent améliorer l'écosystème Ruby.
Une nouvelle version de Ruby MRI - implémentant souvent de nouvelles fonctionnalités de langage, en plus des modifications standard de la bibliothèque - est publiée chaque Noël. Les fonctionnalités sont d'abord implémentées dans Ruby MRI, généralement sur la base de discussions sur la liste de diffusion Ruby Core Developer. D'autres implémentations de Ruby sont à la traîne, dans certains cas même de plusieurs années.
JRuby
JRuby est une version de Ruby implémentée au-dessus de la machine virtuelle Java (JVM). Comme il devient populaire pour les langages au-delà de Java de s'exécuter au-dessus de la JVM (je regarde dans votre direction, Clojure et Scala), une implémentation Ruby basée sur la JVM est susceptible de gagner en popularité.
Ruby dans la JVM signifie également que Ruby peut s'exécuter partout où Java peut s'exécuter (comme les téléphones Android, en utilisant Ruboto par exemple). De plus, grâce à l'interopérabilité de la JVM, le code JRuby peut utiliser la plate-forme Java, y compris les bibliothèques standard et tierces.
JRuby est également utile pour intégrer une solution basée sur Rails dans un environnement de déploiement Java uniquement, en regroupant l'application Rails sous la forme d'un fichier .war
à déployer dans un conteneur Tomcat ou sous la forme d'une applet Java exécutée dans le cadre de votre interface Web. , par exemple.
Pour ceux qui ne sont pas habitués à la JVM, cependant, JRuby apporte des problèmes standard liés à la JVM tels que le démarrage lent de l'interpréteur Ruby, le débogage des problèmes de CLASSPATH si vous utilisez des bibliothèques Java tierces, une plus grande utilisation de la mémoire et le fait que maintenant votre code doit être écrit en tenant compte des considérations de sécurité des threads.
De plus, certaines fonctionnalités de Ruby (les API C et l'un des puissants outils d'introspection de Ruby, le module ObjectSpace) ne sont pas implémentées dans JRuby.
Cela dit, les avantages de l'utilisation de la JVM peuvent l'emporter sur les inconvénients pour certaines situations ou certains projets. La JVM permet de nombreuses optimisations de performances, telles que l'activation du compilateur JIT ou l'utilisation d'objets et d'API Java natifs.
À titre d'exemple d'un cas d'utilisation convaincant de JRuby, un de mes anciens collègues a déjà eu un problème gourmand en CPU qu'il a initialement résolu avec des threads dans Ruby 1.9.3. Lorsqu'il est passé à JRuby et a utilisé les java.util.concurrent.Executors
de Java, il a constaté une amélioration des performances de plusieurs ordres de grandeur (des dizaines de milliers de fois plus rapide) pour cette opération. Voir son expérience ici.
Rubinius
Rubinius est une implémentation de Ruby qui implémente un environnement d'exécution générique pour les langages dynamiques au-dessus d'une machine virtuelle de bas niveau (LLVM). En utilisant cette infrastructure et la technologie de compilateur JIT, Rubinius peut souvent exécuter du code Ruby avec moins de surcharge que MRI.

Rubinius est également construit en utilisant autant de Ruby que possible pour rendre le développement de l'interpréteur / runtime plus rapide et plus facile.
Fait amusant : RubySpec a vu le jour lors de la mise en œuvre de Rubinius.
Comme JRuby, Rubinius inclut un compilateur JIT, une meilleure gestion de la mémoire et une machine virtuelle plus mature que Ruby MRI. Cependant, contrairement à JRuby, Rubinius prend en charge les bibliothèques Ruby C et les fondements de Rubinius sont écrits en C++, pas en Java.
Rubinius peut être un bon compromis lorsque vous avez besoin de hautes performances sur vos serveurs Rails sans la courbe d'apprentissage ou d'autres inconvénients de JRuby.
mrubis
mruby est conçu pour être une version intégrable de Ruby (supportant Ruby 1.9.3). Avec mruby, vous pouvez proposer Ruby comme langage de script/d'automatisation dans les applications natives, l'utiliser pour les scripts de jeu, et même pour programmer des cartes à microcontrôleur comme le Raspberry Pi.
Si votre plate-forme a des contraintes de ressources sévères, mruby peut être juste l'interpréteur Ruby pour vous. mruby est également utilisé pour :
- Créez des applications iOS (en tant que concurrent de RubyMotion, décrit ci-dessous)
- Intégrez Ruby dans les applications iOS, pour une vitesse de développement
- Offrir aux utilisateurs finaux un langage de script intégré à des fins d'automatisation
Avec l'Internet des objets devenant de plus en plus une réalité, la domotique prenant son envol et les ordinateurs extrêmement portables (et relativement puissants) devenant de plus en plus courants, le paysage des plates-formes cibles à prendre en charge se diversifie de plus en plus. mruby permet de le faire avec le même langage productif que celui que l'on utiliserait sur le bureau.
Opale
Opal est un transpileur pour transformer Ruby en JavaScript.
Avec l'essor de Coffeescript, les développeurs apprennent qu'ils n'ont pas besoin de taper JavaScript pour obtenir JavaScript. Bien que Coffeescript ait certes ses avantages, utilisez-le assez longtemps et vous risquez de rencontrer des choses que vous n'aimez pas dans le langage.
Entrez Opal : Tapez Ruby, obtenez Javascript . Plutôt cool.
Opal s'efforce d'être aussi cohérent que possible avec les autres implémentations Ruby et est donc également testé par rapport à un sous-ensemble de RubySpec. Certaines incompatibilités existent cependant, dues à la nature de JavaScript et des runtimes JavaScript. Par exemple, les chaînes et les symboles dans Opal sont égaux, et Opal ne fournit aucun mécanisme de thread ou d'exécution de shell.
Opal fonctionne de manière autonome ou peut être utilisé dans le cadre du pipeline d'actifs Rails (par exemple, pour transpiler automatiquement votre fichier somefile.js.rb
en JavaScript).
Peut-être que vous avez un domaine problématique bien adapté au modèle de concurrence asynchrone de JavaScript (comme un petit service Node.js) mais que vous voulez le langage ou certaines gemmes de l'espace Ruby. Opal peut être une bonne solution pour vous dans ce cas.
Ou peut-être voulez-vous écrire une application Web Ruby complète. Avec Opal, c'est possible. Ayez un interpréteur Ruby exécutant votre code Ruby côté serveur, puis faites en sorte qu'Opal génère du JavaScript pour qu'il s'exécute côté client.
Opal reconnaît que vous interagirez probablement avec d'autres API JavaScript (le DOM ou Node.js par exemple). Il facilite donc la transition vers JavaScript et fournit du sucre syntaxique Ruby par rapport aux bibliothèques JavaScript courantes telles que jQuery.
La nature centrée sur JavaScript d'Opal, cependant, est à la fois sa force et sa faiblesse. En revanche, le runtime d'Opal est le runtime JavaScript, et Opal est informé par les décisions de conception JavaScript. Donc, si vous recherchez une bonne implémentation de Ruby pour écrire un petit script shell, ou si vous recherchez un meilleur environnement d'exécution Ruby pour votre application Rails, Opal n'est probablement pas votre meilleur choix.
RubyMotion
RubyMotion est à la fois (a) une implémentation Ruby (écrite en Objective-C et Cocoa) et (b) un ensemble de liaisons de langage permettant aux développeurs d'accéder aux API Cocoa via Ruby.
RubyMotion est un produit commercial qui vous permet d'écrire des applications natives Cocoa dans Ruby. RubyMotion 2.0 vous permet d'écrire des applications iOS et Mac OS X dans Ruby, et RubyMotion 3 promet d'apporter ce même support à Android.
RubyMotion implémente la version 1.9 du langage Ruby.
Implémentations obsolètes
Au fil des années depuis que Ruby a été introduit pour la première fois, certaines des implémentations Ruby qui ont vu le jour ont été abandonnées ou interrompues, telles que :
- Ruby Enterprise Edition (REE). REE était un fork de MRI 1.8 des gens de Phusion Passenger qui a implémenté de nombreuses améliorations de mémoire et de récupération de place pour les développeurs Web. Pendant plusieurs années, c'était l'implémentation Ruby par défaut déployée pour les sites Rails de production. Cependant, il n'a jamais été mis à jour pour Ruby 1.9 ou Ruby 2.0 et a finalement été abandonné en 2012.
- FerRuby. IronRuby est Ruby implémenté sur Microsoft .NET, écrit en C #, et pendant un certain temps, le projet a été financé par Microsoft. Abandonné en 2011, IronRuby supportait pour la dernière fois Ruby 1.8.6.
Emballer
Il existe une grande variété d'environnements d'exécution et d'interpréteurs parmi lesquels choisir dans le paysage Ruby. Pour la plupart des projets Ruby, l'implémentation de référence Ruby (Ruby MRI) reste l'interpréteur de choix. Cependant, des implémentations Ruby alternatives peuvent très bien être le bon choix pour votre projet, en fonction de vos objectifs et contraintes fonctionnels et techniques.
Dans son rôle d'implémentation de référence de Ruby, MRI obtient plus rapidement de nouvelles fonctionnalités de langage, a suffisamment de simultanéité et d'histoires de mémoire (qui ne font que s'améliorer) et a la compatibilité la plus large avec les gemmes (certaines partiellement écrites en C). Dans l'ensemble, l'IRM est un choix solide et fiable pour le code Ruby à usage général.
Pour les déploiements d'entreprise plus importants, ou pour les situations où vous avez besoin d'interagir avec du code Java (ou d'autres langages JVM) ou avez besoin de modèles de concurrence hautement évolués, JRuby est une option convaincante.
Et bien sûr, si vous avez des besoins uniques (par exemple, écrire du JavaScript, fonctionner sur la génération actuelle d'appareils embarqués, etc.), les autres alternatives Ruby peuvent être exactement ce que vous recherchez.
Avec une grande variété d'environnements d'exécution et d'interpréteurs Ruby parmi lesquels choisir, Ruby se révèle être un langage flexible, utile pour un large éventail d'environnements informatiques, allant d'un gros magasin de déploiement Java d'entreprise à un logiciel qui contrôle ce feu rouge dans votre bureau. vous avez accroché votre Raspberry Pi le week-end dernier. Choisir le bon outil pour le bon usage est essentiel, oui, mais j'espère que cet article vous a montré que Ruby est bien plus que l'interpréteur Ruby par défaut fourni avec votre système d'exploitation.
Le monde de Ruby est grandement amélioré par des équipes de mise en œuvre alternatives de Ruby travaillant avec l'équipe principale de Ruby MRI au fur et à mesure que des modifications du langage sont proposées. Ils ajoutent de la diversité à la communauté d'implémentation Ruby, en ajoutant leurs expériences d'implémentation Ruby durement gagnées et leurs propres points de vue sur les fonctionnalités entrant dans le langage. Les passionnés de Ruby doivent collectivement à ces équipes une grande dette de gratitude. Bravo à eux pour leurs efforts !