Rubyプログラミング言語の多くのインタープリターとランタイム
公開: 2022-03-11序章
Ruby Gemには多くの色合いがあるように、Rubyインタープリターには複数の実装があります。
最も一般的に使用されるRubyインタープリターは、Rubyの作成者(まつもとゆきひろ)とRubyコアチームによってCで開発されたリファレンス実装RubyMRIです。
Ruby on Rails採用ガイドには、Railsのいくつかの欠点は、代替のRubyインタープリターを使用することで解決または回避できる可能性があると記載されています。 この記事では、現在利用可能なさまざまな既存のRubyインタープリターの実装とランタイムを紹介し、それぞれの長所と短所について説明します。
Rubyのバージョン履歴(およびそれが代替実装にどのように影響するか)
残念ながら、Ruby用のPython言語リファレンスに相当するものはありません(ISO / IEC30170:2012はRuby 1.8 / Ruby 1.9について説明していますが、Ruby 2.xに対応する仕様はありません)。 そのような言語仕様がない場合、Ruby実装者は通常、コミュニティ主導のRubySpecに依存します。これは、任意のRubyインタープリターで実行できるテストを通じてRuby言語の予想される動作を指定します。 したがって、RubySpecは、Ruby実装がデファクトスタンダードに準拠していることを検証するためにRuby実装者によって使用されます。
正式な仕様がないため、Rubyの新しいリリースは、RubyMRIの新しいリリースに対応していることがよくあります。 Ruby(言語)をRubyMRIから分離するための設計プロセスについて説明している未解決の問題があることは注目に値します。
ただし、Ruby言語とMRIリファレンス実装の間の現在の緊密な結合を考えると、代替Ruby実装の開発者は、新しいMRIリリースごとに導入された言語の変更に追いつくのに苦労することがあります。
Ruby1.8とRuby1.9の間の移行ほど、これほど困難なことはありませんでした。 2007年、Rubyの構文をクリーンアップして統合するために(Ruby 1.0のリリースから10年で言語が進化したため)、RubyコアチームはRuby 1.9.0をリリースしました。これは、言語に多くの後方互換性を導入したバージョンです。 。 その結果、すべてのRuby実装が構文を1.8から1.9にジャンプさせるために必要な労力を費やしたわけではありません。 そのため、コミュニティで使用されなくなった1.8ベースのRuby実装がいくつかありますが、オンラインで見つけたり、古いRubyの手で話したりすることができます。
セマンティックバージョニングの原則に従って、RubyMRIの新しいバージョンが毎年クリスマスにリリースされます。 Ruby 2.0(2013年リリース)および2.1(2014年リリース)はそれぞれ、Ruby 1.9との下位互換性を失うことなく、Ruby開発者が利用できる追加の言語機能を導入しました。
なぜ代替のRuby実装を使用するのですか? MRIの何が問題になっていますか?
さまざまな代替Ruby実装があり、さまざまなユースケースと環境をサポートしています。 JavaEnterprise環境。 モバイルアプリケーション。 JavaScriptの実装。 低CPU/RAMマシン。 これらのユースケースをサポートすることに加えて、代替の実装では、アプリケーションの特性に応じて、速度をさらに向上させたり、メモリ使用率をより効率的にしたりすることもできます。
長い間、多くのRubyonRails開発者はMRIの代わりにRubyEnterpriseEdition(REE)を使用し、当時のMRIバージョンと比較してREEの優れたメモリ管理技術を利用していました。 (REEはその後2012年に廃止されました。)
MRIはデフォルトのRuby実装ですが、すべての環境とシナリオで必ずしも正しい選択であるとは限りません。 たとえば、MRIの同時実行サポートは、JRubyやRubiniusのサポートよりも劣っています。 また、MRIのメモリとガベージコレクションのスキームは絶えず改善されていますが、それでもいくつかの問題があります。
以下のRuby実装の調査は、プロジェクトの運用目標と制約に最も適したインタープリターを選択するのに役立つことを目的としています。
MatzのRubyインタープリター(MRI)/ CRuby
まつもとゆきひろ(Rubyの作成者である「Matz」)が率いるRubyコアチームによってCで記述された、MRIは、デファクトスタンダードとして機能するRubyのリファレンス実装です。 たとえば、OSベンダーがOSにインストールされたソフトウェアの一部としてRubyのバージョンを含めている場合、それは通常MRIバージョンです。 MRIは、他のどのRuby実装よりも多くの有料コアチームメンバーから恩恵を受けているだけでなく、Rubyエコシステムを改善したい人々や企業から捧げられたリソースを提供しています。
Ruby MRIの新しいバージョン(多くの場合、標準ライブラリの変更に加えて、新しい言語機能を実装しています)が毎年クリスマスにリリースされます。 機能は最初にRubyMRIに実装され、通常はRubyコア開発者のメーリングリストでの議論に基づいています。 他のRubyの実装は、場合によっては何年も遅れています。
JRuby
JRubyは、Java仮想マシン(JVM)上に実装されたRubyのバージョンです。 Java以外の言語がJVM上で実行されることが一般的になるにつれて(私はあなたの方向を見ています、ClojureとScala)、JVMベースのRuby実装が人気を博す可能性があります。
JVM内のRubyは、RubyがJavaを実行できる場所ならどこでも実行できることも意味します(たとえば、Rubotoを使用するAndroidフォンなど)。 さらに、JVMの相互運用性のおかげで、JRubyコードは標準ライブラリとサードパーティライブラリの両方を含むJavaプラットフォームを利用できます。
JRubyは、RailsベースのソリューションをJavaのみのデプロイメント環境に導入したり、Railsアプリを.war
ファイルとしてパッケージ化してTomcatコンテナーにデプロイしたり、Webフロントエンドの一部として実行されているJavaアプレットとして使用したりする場合にも役立ちます。 、 例えば。
ただし、JVMに慣れていない人のために、JRubyは、Rubyインタープリターの起動が遅い、サードパーティのJavaライブラリを使用している場合のCLASSPATHの問題のデバッグ、メモリ使用量の増加、コードがスレッドセーフの考慮事項を念頭に置いて作成する必要があります。
また、Rubyの一部の機能(C API、およびRubyの強力なイントロスペクションツールの1つであるObjectSpaceモジュール)は、JRubyに実装されていません。
とはいえ、JVMを使用することの利点は、特定の状況やプロジェクトの欠点を上回る場合があります。 JVMを使用すると、JITコンパイラーをオンにしたり、ネイティブJavaオブジェクトやAPIを使用したりするなど、多くのパフォーマンスを最適化できます。
説得力のあるJRubyのユースケースの例として、私の元同僚はかつてCPUを集中的に使用する問題を抱えていましたが、最初はRuby1.9.3のスレッドで解決しました。 彼がJRubyに切り替えて、Javaのjava.util.concurrent.Executors
を使用したとき、彼はこの操作で数桁(数万倍高速)のパフォーマンスの向上を確認しました。 ここで彼の実験を参照してください。
ルビニウス
Rubiniusは、低レベル仮想マシン(LLVM)上に動的言語の汎用ランタイムを実装するRubyの実装です。 このインフラストラクチャとJITコンパイラテクノロジを使用すると、RubiniusはMRIよりも少ないオーバーヘッドでRubyコードを実行できることがよくあります。
Rubiniusは、インタープリター/ランタイムの開発をより速く簡単にするために、可能な限り多くのRubyを使用して構築されています。

おもしろい事実:RubySpecは当初Rubiniusを実装する過程で生まれました。
JRubyと同様に、Rubiniusには、Ruby MRIよりも優れたJITコンパイラ、優れたメモリ管理、およびより成熟した仮想マシンが含まれています。 ただし、JRubyとは異なり、RubiniusはRuby Cライブラリをサポートし、Rubiniusの基盤はJavaではなくC++で記述されています。
Rubiniusは、JRubyの学習曲線やその他の欠点なしに、Railsサーバーで高性能が必要な場合に適した中間点になる可能性があります。
mruby
mrubyは、Rubyの埋め込み可能なバージョン(Ruby 1.9.3をサポート)になるように設計されています。 mrubyを使用すると、ネイティブアプリケーションのスクリプト/自動化言語としてRubyを提供し、ゲームのスクリプト、さらにはRaspberryPiのようなマイクロコントローラーボードのプログラミングにも使用できます。
プラットフォームに厳しいリソース制約がある場合、mrubyは単なるRubyインタープリターである可能性があります。 mrubyは次の目的にも使用されています。
- iOSアプリを構築する(RubyMotionの競合製品として、以下で説明します)
- 開発速度を上げるために、RubyをiOSアプリに埋め込みます
- 自動化の目的でエンドユーザーに埋め込みスクリプト言語を提供する
モノのインターネットがますます現実になり、ホームオートメーションが独自のものになり、非常にポータブルな(そして比較的強力な)コンピューターが一般的になるにつれて、サポートするターゲットプラットフォームの状況はますます多様化しています。 mrubyは、デスクトップで使用するのと同じ生産的な言語でそれを可能にするのに役立ちます。
オパール
Opalは、RubyをJavaScriptに変換するトランスパイラーです。
Coffeescriptの台頭により、開発者はJavaScriptを取得するためにJavaScriptを入力する必要がないことを学んでいます。 Coffeescriptには確かにその利点がありますが、それを十分に長く使用すると、その言語について気に入らないことに遭遇することになります。
オパールと入力: Rubyと入力し、Javascriptを取得します。 かなりクール。
Opalは、他のRuby実装と可能な限り一貫性を保つように努めているため、RubySpecのサブセットに対してもテストされています。 ただし、JavaScriptとJavaScriptランタイムの性質に起因する、いくつかの非互換性が存在します。 たとえば、Opalの文字列とシンボルは等しく、Opalはスレッド化またはシェル実行メカニズムを提供しません。
Opalはスタンドアロンで実行されるか、Railsアセットパイプラインの一部として使用できます(たとえば、 somefile.js.rb
ファイルをJavaScriptに自動的にトランスパイルするため)。
JavaScriptの非同期同時実行パターン(小さなNode.jsサービスなど)に適した問題のあるドメインがありますが、Rubyスペースの言語または特定のgemが必要な場合があります。 その場合、オパールはあなたにとって良い解決策かもしれません。
または、フルスタックのRubyWebアプリを作成したい場合もあります。 オパールを使用すると、できます。 サーバー側のRubyコードを実行するRubyインタープリターを1つ用意し、クライアント側で実行するJavaScriptを生成するOpalを用意します。
Opalは、他のJavaScript API(DOM、Node.jsなど)とやり取りする可能性があることを認識しています。 したがって、JavaScriptへの移行が容易になり、jQueryなどの一般的なJavaScriptライブラリよりもRubyの構文上の糖衣構文が提供されます。
ただし、OpalのJavaScript中心の性質は、その長所と短所の両方です。 欠点として、OpalのランタイムはJavaScriptランタイムであり、OpalはJavaScriptの設計上の決定によって通知されます。 したがって、小さなシェルスクリプトを作成するためのRubyの優れた実装を探している場合、またはRailsアプリ用のより優れたRubyランタイムを探している場合、Opalはおそらく最良の選択ではありません。
RubyMotion
RubyMotionは、(a)Ruby実装(Objective-CとCocoaを使用して記述)と(b)開発者がRubyを介してCocoaAPIにアクセスできるようにする一連の言語バインディングの両方です。
RubyMotionは、RubyでCocoaネイティブアプリを作成できるようにする商用製品です。 RubyMotion 2.0を使用すると、iOSおよびMac OS XアプリをRubyで作成でき、RubyMotion3はこれと同じサポートをAndroidに提供することを約束します。
RubyMotionは、Ruby言語のバージョン1.9を実装しています。
廃止された実装
Rubyが最初に導入されてから何年にもわたって、次のようなRubyの実装の一部が放棄または廃止されました。
- Ruby Enterprise Edition(REE)。 REEは、PhusionPassengerの人々からのMRI1.8のフォークであり、Web開発者向けに多くのメモリとガベージコレクションの改善を実装しました。 数年間、これは本番RailsサイトにデプロイされたデフォルトのRuby実装でした。 ただし、Ruby1.9またはRuby2.0用に更新されることはなく、最終的には2012年に廃止されました。
- IronRuby。 IronRubyは、Microsoft .NET上に実装されたRubyであり、C#で記述されており、しばらくの間、プロジェクトはMicrosoftによって資金提供されていました。 2011年に放棄されたIronRubyは、最後にRuby1.8.6をサポートしていました。
要約
Rubyランドスケープでは、さまざまなランタイムとインタープリターから選択できます。 ほとんどのRubyプロジェクトでは、Rubyリファレンス実装(Ruby MRI)が引き続きインタープリターとして選択されます。 ただし、機能的および技術的な目標と制約によっては、代替のRuby実装がプロジェクトに適している場合があります。
Rubyのリファレンス実装としての役割において、MRIは新しい言語機能をより高速に取得し、十分な並行性とメモリストーリー(改善されているだけです)を備え、gemとの互換性が最も広くなっています(一部はCで記述されています)。 全体として、MRIは、汎用Rubyコードにとって確実で信頼できる選択肢です。
大規模なエンタープライズ展開の場合、またはJavaコード(または他のJVM言語)と対話する必要がある場合、または高度に進化した同時実行パターンが必要な場合、JRubyは魅力的なオプションです。
そしてもちろん、独自のニーズがある場合(たとえば、JavaScriptの記述、現世代の組み込みデバイスでの実行など)、他のRubyの代替手段がまさにあなたが探しているものかもしれません。
多種多様なRubyランタイムとインタープリターから選択できるため、Rubyは柔軟な言語であり、企業の大規模なJavaデプロイメントショップから、オフィスのストップライトを制御するソフトウェアまで、さまざまなコンピューティング環境に役立ちます。あなたは先週末にRaspberryPiをフックしました。 適切な目的のために適切なツールを選択することは不可欠ですが、この記事が、RubyがOSに付属しているデフォルトのRubyインタープリターよりもはるかに優れていることを示していることを願っています。
言語の変更が提案されると、Rubyの世界はコアRubyMRIチームと連携する代替のRuby実装チームによって大幅に強化されます。 彼らはRuby実装コミュニティに多様性を追加し、苦労して獲得したRuby実装経験と、言語に組み込まれる機能に関する独自の視点を追加します。 Ruby愛好家は、これらのチームに多大な感謝の意を表しています。 彼らの努力に対する称賛!