Die vielen Interpreter und Laufzeiten der Programmiersprache Ruby

Veröffentlicht: 2022-03-11

Einführung

So wie es viele Schattierungen des Rubin-Edelsteins gibt, gibt es mehrere Implementierungen des Ruby-Interpreters.

Der am häufigsten verwendete Ruby-Interpreter ist die Referenzimplementierung Ruby MRI, die vom Schöpfer von Ruby (Yukihiro Matsumoto) und dem Ruby-Kernteam in C entwickelt wurde.

Unser Ruby on Rails Hiring Guide erwähnt, dass einige der Nachteile in Rails möglicherweise durch die Verwendung eines alternativen Ruby-Interpreters gelöst oder vermieden werden können. Dieser Artikel stellt die verschiedenen existierenden Ruby-Interpreter-Implementierungen und -Laufzeiten vor, die heute verfügbar sind, und diskutiert die jeweiligen Vor- und Nachteile.

Eine Liste von Ruby-Interpretern und Laufzeiten, einschließlich mruby, JRuby, RubyMotion, Rubinius und Ruby MRI

Ruby-Versionsgeschichte (und wie sie sich auf alternative Implementierungen auswirkt)

Leider gibt es kein Äquivalent zur Python Language Reference für Ruby (ISO/IEC 30170:2012 beschreibt Ruby 1.8 / Ruby 1.9, aber es gibt keine entsprechende Spezifikation für Ruby 2.x). In Ermangelung einer solchen Sprachspezifikation verlassen sich Ruby-Implementierer normalerweise stattdessen auf die Community-gesteuerte RubySpec, die das erwartete Verhalten der Ruby-Sprache durch Tests spezifiziert, die in jedem Ruby-Interpreter ausgeführt werden können. RubySpec wird daher von Ruby-Implementierern verwendet, um die Verhaltenskonformität ihrer Ruby-Implementierungen mit dem De-facto-Standard zu überprüfen.

Aufgrund des Fehlens einer formalen Spezifikation entsprechen neue Releases von Ruby oft einfach neuen Releases von Ruby MRI. Es ist erwähnenswert, dass es ein offenes Problem gibt, in dem ein Designprozess zur Entkopplung von Ruby (der Sprache) von der Ruby-MRT diskutiert wird.

Angesichts der derzeitigen engen Kopplung zwischen der Ruby-Sprache und der MRI-Referenzimplementierung haben Entwickler alternativer Ruby-Implementierungen jedoch manchmal Schwierigkeiten, mit den Sprachänderungen Schritt zu halten, die in jeder neuen MRI-Version eingeführt werden.

Nie war dies schwieriger als beim Übergang zwischen Ruby 1.8 und Ruby 1.9. Im Jahr 2007 veröffentlichte das Ruby-Kernteam Ruby 1.9.0, eine Version, die viele Rückwärtsinkompatibilitäten in die Sprache einführte, um die Syntax von Ruby zu bereinigen und zu konsolidieren (da sich die Sprache in den zehn Jahren seit der Veröffentlichung von Ruby 1.0 entwickelt hatte). . Infolgedessen investierten nicht alle Ruby-Implementierungen den notwendigen Aufwand, um den syntaktischen Sprung von 1.8 auf 1.9 zu schaffen. Daher gibt es mehrere 1.8-basierte Ruby-Implementierungen, die von der Community nicht mehr verwendet werden, die Sie aber möglicherweise noch online finden oder von alten Ruby-Händen besprochen werden.

Jedes Jahr zu Weihnachten wird eine neue Version von Ruby MRI veröffentlicht, die einem semantischen Versionierungsprinzip folgt. Ruby 2.0 (veröffentlicht 2013) und 2.1 (veröffentlicht 2014) führten jeweils zusätzliche Sprachfunktionen ein, die Ruby-Entwickler nutzen können, ohne die Abwärtskompatibilität mit Ruby 1.9 einzubüßen.

Warum eine alternative Ruby-Implementierung verwenden? Was ist falsch am MRT?

Es gibt eine Vielzahl alternativer Ruby-Implementierungen, die eine Vielzahl von Anwendungsfällen und Umgebungen unterstützen. Java Enterprise-Umgebungen. Mobile Anwendungen. JavaScript-Implementierungen. Niedrige CPU/RAM-Maschinen. Neben der Unterstützung dieser Anwendungsfälle können alternative Implementierungen je nach den Eigenschaften Ihrer Anwendung manchmal auch einen zusätzlichen Geschwindigkeitsschub oder eine effizientere Speichernutzung bieten.

Lange Zeit verwendeten viele Ruby on Rails-Entwickler Ruby Enterprise Edition (REE) anstelle von MRI und profitierten von den besseren Speicherverwaltungstechniken in REE im Vergleich zur damaligen MRI-Version. (REE wurde später jedoch im Jahr 2012 eingestellt.)

MRI ist zwar die standardmäßige Ruby-Implementierung, aber nicht unbedingt die richtige Wahl für alle Umgebungen und Szenarien. Beispielsweise ist die Nebenläufigkeitsunterstützung von MRI der von JRuby oder Rubinius unterlegen. Obwohl sich die Speicher- und Garbage-Collection-Schemata von MRI ständig verbessern, gibt es immer noch einige Probleme.

Die folgende Übersicht über Ruby-Implementierungen soll Sie bei der Auswahl des Interpreters unterstützen, der für die betrieblichen Ziele und Einschränkungen Ihres Projekts am besten geeignet ist.

Matz's Ruby Interpreter (MRI) / CRuby

MRI wurde vom Ruby-Kernteam unter der Leitung von Yukihiro Matsumoto („Matz“, der Schöpfer von Ruby) in C geschrieben und ist die Referenzimplementierung von Ruby, die als De-facto-Standard dient. Wenn ein Betriebssystemanbieter beispielsweise eine Version von Ruby als Teil der installierten Betriebssystemsoftware enthält, ist dies normalerweise die MRI-Version. MRI profitiert von mehr bezahlten Kernteammitgliedern als jede andere Ruby-Implementierung sowie von bereitgestellten Ressourcen von Personen oder Unternehmen, die das Ruby-Ökosystem verbessern möchten.

Jedes Jahr zu Weihnachten wird eine neue Version von Ruby MRI veröffentlicht, die neben Standardbibliotheksänderungen häufig neue Sprachfunktionen implementiert. Funktionen werden zuerst in Ruby MRI implementiert, normalerweise basierend auf Diskussionen auf der Mailingliste der Ruby-Core-Entwickler. Andere Ruby-Implementierungen hinken hinterher, teilweise sogar um Jahre.

JRuby

JRuby ist eine Version von Ruby, die auf der Java Virtual Machine (JVM) implementiert ist. Da es immer beliebter wird, dass Sprachen über Java hinaus auf der JVM laufen (ich schaue in Ihre Richtung, Clojure und Scala), wird eine JVM-basierte Ruby-Implementierung wahrscheinlich an Popularität gewinnen.

Ruby in der JVM bedeutet auch, dass Ruby überall laufen kann, wo Java laufen kann (wie Android-Telefone, zum Beispiel mit Ruboto). Darüber hinaus kann JRuby-Code dank der Interoperabilität der JVM die Java-Plattform nutzen, einschließlich sowohl Standard- als auch Drittanbieter-Bibliotheken.

JRuby ist auch nützlich, um eine Rails-basierte Lösung in eine reine Java-Bereitstellungsumgebung zu bringen, die Rails-App als .war -Datei zu verpacken, um sie in einem Tomcat-Container bereitzustellen, oder als Java-Applet, das als Teil Ihres Web-Front-Ends ausgeführt wird , zum Beispiel.

Für diejenigen, die nicht an die JVM gewöhnt sind, bringt JRuby jedoch Standard-JVM-bezogene Probleme mit sich, wie z muss unter Berücksichtigung der Thread-Sicherheit geschrieben werden.

Außerdem sind einige Funktionen von Ruby (C-APIs und eines der leistungsstarken Introspektion-Tools von Ruby, das ObjectSpace-Modul) nicht in JRuby implementiert.

Trotzdem können die Vorteile der Verwendung der JVM die Nachteile für bestimmte Situationen oder Projekte überwiegen. Die JVM ermöglicht viele Leistungsoptimierungen, z. B. das Einschalten des JIT-Compilers oder die Verwendung nativer Java-Objekte und APIs.

Als Beispiel für einen überzeugenden JRuby-Anwendungsfall hatte ein ehemaliger Kollege von mir einmal ein CPU-intensives Problem, das er zunächst mit Threads in Ruby 1.9.3 löste. Als er zu JRuby wechselte und java.util.concurrent.Executors von Java verwendete, sah er eine Leistungsverbesserung von mehreren Größenordnungen (Zehntausendfach schneller) für diese Operation. Sehen Sie hier sein Experiment.

Rubinius

Rubinius ist eine Implementierung von Ruby, die eine generische Laufzeitumgebung für dynamische Sprachen auf einer Low Level Virtual Machine (LLVM) implementiert. Mit dieser Infrastruktur und der JIT-Compiler-Technologie kann Rubinius Ruby-Code oft mit weniger Overhead als MRI ausführen.

Rubinius wurde auch mit so viel Ruby wie möglich gebaut, um die Entwicklung des Interpreters / der Laufzeit schneller und einfacher zu machen.

Fun Fact: RubySpec ist ursprünglich im Zuge der Implementierung von Rubinius entstanden.

Wie JRuby enthält Rubinius einen JIT-Compiler, eine bessere Speicherverwaltung und eine ausgereiftere virtuelle Maschine als Ruby MRI. Im Gegensatz zu JRuby unterstützt Rubinius jedoch Ruby-C-Bibliotheken, und die Grundlagen von Rubinius sind in C++ und nicht in Java geschrieben.

Rubinius kann ein guter Mittelweg sein, wenn Sie eine hohe Leistung auf Ihren Rails-Servern ohne die Lernkurve oder andere Nachteile von JRuby benötigen.

mruby

mruby ist als einbettbare Version von Ruby konzipiert (unterstützt Ruby 1.9.3). Mit mruby können Sie Ruby als Skript-/Automatisierungssprache in nativen Anwendungen anbieten, es für das Skripting von Spielen und sogar zum Programmieren von Mikrocontroller-Boards wie dem Raspberry Pi verwenden.

Wenn Ihre Plattform starke Ressourcenbeschränkungen hat, ist mruby möglicherweise genau der richtige Ruby-Interpreter für Sie. mruby wird auch verwendet für:

  • Erstellen Sie iOS-Apps (als Konkurrent von RubyMotion, siehe unten)
  • Betten Sie Ruby in iOS-Apps ein, um die Entwicklung zu beschleunigen
  • Bieten Sie Endbenutzern eine eingebettete Skriptsprache für Automatisierungszwecke an

Da das Internet der Dinge immer mehr zur Realität wird, die Heimautomatisierung immer mehr an Bedeutung gewinnt und extrem tragbare (und relativ leistungsstarke) Computer immer häufiger vorkommen, wird die Landschaft der zu unterstützenden Zielplattformen immer vielfältiger. mruby hilft dabei, dies mit der gleichen produktiven Sprache zu tun, die man auf dem Desktop verwenden würde.

Opal

Opal ist ein Transpiler, der Ruby in JavaScript umwandelt.

Mit dem Aufstieg von Coffeescript lernen Entwickler, dass sie kein JavaScript eingeben müssen, um JavaScript zu erhalten . Während Coffeescript zugegebenermaßen seine Vorteile hat, verwenden Sie es lange genug und Sie werden zwangsläufig auf Dinge stoßen, die Ihnen an der Sprache nicht gefallen.

Geben Sie Opal ein: Geben Sie Ruby ein, erhalten Sie Javascript . Ziemlich cool.

Opal ist bestrebt, so konsistent wie möglich mit anderen Ruby-Implementierungen zu sein und wird daher auch gegen eine Teilmenge von RubySpec getestet. Es gibt jedoch einige Inkompatibilitäten, die sich aus der Natur von JavaScript und JavaScript-Laufzeiten ergeben. Beispielsweise sind Zeichenfolgen und Symbole in Opal gleich, und Opal bietet keine Threading- oder Shell-Ausführungsmechanismen.

Opal läuft eigenständig oder kann als Teil der Rails-Asset-Pipeline verwendet werden (z. B. um Ihre Datei somefile.js.rb automatisch in JavaScript zu transpilieren).

Vielleicht haben Sie eine Problemdomäne, die sich gut für das asynchrone Nebenläufigkeitsmuster von JavaScript eignet (z. B. ein kleiner Node.js-Dienst), möchten aber die Sprache oder bestimmte Edelsteine ​​​​aus dem Ruby-Bereich. Opal kann in diesem Fall eine gute Lösung für Sie sein.

Oder vielleicht möchten Sie eine Full-Stack-Ruby-Web-App schreiben. Mit Opal ist das möglich. Lassen Sie einen Ruby-Interpreter Ihren serverseitigen Ruby-Code ausführen und lassen Sie dann Opal JavaScript generieren, das auf der Client-Seite ausgeführt wird.

Opal erkennt, dass Sie wahrscheinlich mit anderen JavaScript-APIs (z. B. dem DOM oder Node.js) interagieren werden. Es erleichtert daher den Übergang zu JavaScript und bietet etwas syntaktischen Ruby-Zucker gegenüber gängigen JavaScript-Bibliotheken wie jQuery.

Die JavaScript-zentrierte Natur von Opal ist jedoch sowohl seine Stärke als auch seine Schwäche. Auf der anderen Seite ist die Laufzeit von Opal die JavaScript-Laufzeit, und Opal wird durch JavaScript-Entwurfsentscheidungen informiert. Wenn Sie also nach einer guten Implementierung von Ruby suchen, um damit ein kleines Shell-Skript zu schreiben, oder nach einer besseren Ruby-Laufzeitumgebung für Ihre Rails-App suchen, ist Opal wahrscheinlich nicht die beste Wahl.

RubyMotion

RubyMotion ist sowohl (a) eine Ruby-Implementierung (geschrieben mit Objective-C und Cocoa) als auch (b) eine Reihe von Sprachbindungen, damit Entwickler über Ruby auf Cocoa-APIs zugreifen können.

RubyMotion ist ein kommerzielles Produkt, mit dem Sie Cocoa-native Apps in Ruby schreiben können. RubyMotion 2.0 ermöglicht es Ihnen, iOS- und Mac OS X-Apps in Ruby zu schreiben, und RubyMotion 3 verspricht, diese gleiche Unterstützung für Android zu bringen.

RubyMotion implementiert Version 1.9 der Sprache Ruby.

Verstorbene Implementierungen

Im Laufe der Jahre seit der Einführung von Ruby wurden einige der entstandenen Ruby-Implementierungen aufgegeben oder eingestellt, wie zum Beispiel:

  • Ruby Enterprise Edition (REE). REE war ein Fork von MRI 1.8 von den Leuten bei Phusion Passenger, der viele Speicher- und Garbage-Collection-Verbesserungen für Webentwickler implementierte. Mehrere Jahre lang war es die standardmäßige Ruby-Implementierung, die für Produktions-Rails-Sites bereitgestellt wurde. Es wurde jedoch nie für Ruby 1.9 oder Ruby 2.0 aktualisiert und schließlich 2012 eingestellt.
  • EisenRubin. IronRuby ist Ruby, das auf Microsoft .NET implementiert und in C# geschrieben wurde, und für eine Weile wurde das Projekt von Microsoft finanziert. IronRuby wurde 2011 aufgegeben und unterstützte zuletzt Ruby 1.8.6.

Einpacken

In der Ruby-Landschaft stehen eine Vielzahl von Laufzeiten und Interpretern zur Auswahl. Für die meisten Ruby-Projekte bleibt die Ruby-Referenzimplementierung (Ruby MRI) der Interpreter der Wahl. Alternative Ruby-Implementierungen können jedoch sehr wohl die richtige Wahl für Ihr Projekt sein, abhängig von Ihren funktionalen und technischen Zielen und Einschränkungen.

In seiner Rolle als Referenzimplementierung von Ruby erhält MRI neue Sprachfunktionen schneller, hat ausreichend Parallelität und Speichergeschichten (die nur noch besser werden) und hat die größte Kompatibilität mit Gems (einige teilweise in C geschrieben). Alles in allem ist MRI eine solide, zuverlässige Wahl für universellen Ruby-Code.

Für größere Unternehmensimplementierungen oder für Situationen, in denen Sie entweder mit Java-Code (oder anderen JVM-Sprachen) interagieren müssen oder hochentwickelte Parallelitätsmuster benötigen, ist JRuby eine überzeugende Option.

Und wenn Sie spezielle Anforderungen haben (z. B. JavaScript schreiben, auf eingebetteten Geräten der aktuellen Generation laufen usw.), sind die anderen Ruby-Alternativen möglicherweise genau das, wonach Sie suchen.

Mit einer Vielzahl von Ruby-Laufzeiten und Interpretern zur Auswahl erweist sich Ruby als flexible Sprache, die für eine Vielzahl von Computerumgebungen nützlich ist, von einem großen Java-Deployment-Shop für Unternehmen bis hin zu Software, die diese Ampel in Ihrem Büro steuert Sie haben Ihren Raspberry Pi letztes Wochenende angeschlossen. Die Auswahl des richtigen Tools für den richtigen Zweck ist wichtig, ja, aber hoffentlich hat Ihnen dieser Artikel gezeigt, dass Ruby so viel mehr ist als der standardmäßige Ruby-Interpreter, der mit Ihrem Betriebssystem geliefert wurde.

Die Welt von Ruby wird durch alternative Ruby-Implementierungsteams, die mit dem Kernteam von Ruby MRI zusammenarbeiten, erheblich erweitert, wenn Änderungen an der Sprache vorgeschlagen werden. Sie bringen Vielfalt in die Ruby-Implementierungs-Community, indem sie ihre hart erkämpften Ruby-Implementierungserfahrungen und ihre eigenen Perspektiven auf Funktionen, die in die Sprache einfließen, einbringen. Rubin-Enthusiasten sind diesen Teams gemeinsam zu großem Dank verpflichtet. Kudos für ihre Bemühungen!