Ruby 編程語言的眾多解釋器和運行時
已發表: 2022-03-11介紹
就像 ruby gem 有很多不同的部分一樣,Ruby 解釋器也有多種實現。
最常用的 Ruby 解釋器是參考實現 Ruby MRI,它由 Ruby 的創建者(Yukihiro Matsumoto)和 Ruby 核心團隊用 C 語言開發。
我們的 Ruby on Rails 招聘指南提到 Rails 中的一些缺點可以通過使用替代的 Ruby 解釋器來解決或避免。 本文展示了當今可用的各種現有 Ruby 解釋器實現和運行時,並討論了它們的優缺點。
Ruby 版本歷史(以及它如何影響替代實現)
遺憾的是,Ruby 沒有對應的 Python 語言參考(ISO/IEC 30170:2012 描述了 Ruby 1.8 / Ruby 1.9,但沒有針對 Ruby 2.x 的相應規範)。 在沒有任何此類語言規範的情況下,Ruby 實現者通常依賴於社區驅動的 RubySpec,該規範通過可以在任何 Ruby 解釋器中運行的測試來指定 Ruby 語言的預期行為。 因此,Ruby 實現者使用 RubySpec 來驗證他們的 Ruby 實現在行為上是否符合事實標準。
由於缺乏正式的規範,Ruby 的新版本通常簡單地對應於 Ruby MRI 的新版本。 值得注意的是,有一個未解決的問題討論了將 Ruby(語言)與 Ruby MRI 分離的設計過程。
然而,鑑於當前 Ruby 語言和 MRI 參考實現之間的緊密耦合,替代 Ruby 實現的開發人員有時很難跟上每個新 MRI 版本中引入的語言變化。
在 Ruby 1.8 和 Ruby 1.9 之間的轉換中,從來沒有比這更困難的了。 2007 年,為了清理和整合 Ruby 的語法(自從 Ruby 1.0 發布以來,這門語言已經發展了十年),Ruby 核心團隊發布了 Ruby 1.9.0,該版本在該語言中引入了許多向後不兼容的問題. 因此,並不是所有的 Ruby 實現都投入了必要的努力來實現從 1.8 到 1.9 的語法跳躍。 因此,有幾個基於 1.8 的 Ruby 實現不再被社區使用,但您仍然可以在網上找到或被老 Ruby 手談論。
遵循語義版本控制原則,每年聖誕節都會發布一個新版本的 Ruby MRI。 Ruby 2.0(2013 年發布)和 2.1(2014 年發布)都引入了額外的語言特性,Ruby 開發人員可以利用這些特性,而不會失去與 Ruby 1.9 的向後兼容性。
為什麼要使用替代的 Ruby 實現? 核磁共振有什麼問題?
有多種替代 Ruby 實現,支持廣泛的用例和環境。 Java 企業環境。 移動應用程序。 JavaScript 實現。 低 CPU/RAM 機器。 除了支持這些用例之外,替代實現有時還可以提供額外的速度提升或更有效的內存利用率,具體取決於應用程序的特性。
很長一段時間以來,許多 Ruby on Rails 開發人員使用 Ruby 企業版 (REE) 代替 MRI,與當時的 MRI 版本相比,利用了 REE 中更好的內存管理技術。 (REE 隨後在 2012 年停產。)
雖然 MRI 是默認的 Ruby 實現,但它不一定是所有環境和場景的正確選擇。 例如,MRI 的並發支持不如 JRuby 或 Rubinius。 此外,儘管 MRI 的內存和垃圾收集方案在不斷改進,但它們仍然存在一些問題。
下面的 Ruby 實現調查旨在幫助您選擇最適合您項目的操作目標和約束的解釋器。
Matz 的 Ruby 解釋器 (MRI) / CRuby
MRI 由 Yukihiro Matsumoto(“Matz”,Ruby 的創建者)領導的 Ruby 核心團隊用 C 語言編寫,是 Ruby 的參考實現,是事實上的標準。 例如,如果操作系統供應商將 Ruby 版本作為操作系統安裝軟件的一部分,則通常是 MRI 版本。 MRI 受益於比任何其他 Ruby 實現更多的付費核心團隊成員,以及來自希望改進 Ruby 生態系統的個人或公司的專用資源。
每年聖誕節都會發布一個新版本的 Ruby MRI - 除了標準庫更改之外,還經常實現新的語言功能。 功能首先在 Ruby MRI 中實現,通常基於 Ruby 核心開發人員郵件列表上的討論。 其他 Ruby 實現滯後,在某些情況下甚至落後數年。
JRuby
JRuby 是在 Java 虛擬機 (JVM) 之上實現的 Ruby 版本。 隨著 Java 以外的語言在 JVM 之上運行變得流行(我正在尋找你的方向,Clojure 和 Scala),基於 JVM 的 Ruby 實現可能會越來越流行。
JVM 中的 Ruby 還意味著 Ruby 可以在 Java 可以運行的任何地方運行(比如 Android 手機,例如使用 Ruboto)。 此外,由於 JVM 的互操作性,JRuby 代碼可以利用 Java 平台,包括標準庫和 3rd 方庫。
JRuby 還可用於將基於 Rails 的解決方案引入純 Java 部署環境,將 Rails 應用程序打包為.war
文件以部署到 Tomcat 容器,或作為 Java 小程序作為 Web 前端的一部分運行, 例如。
但是,對於那些不習慣 JVM 的人來說,JRuby 帶來了與標準 JVM 相關的問題,例如 Ruby 解釋器的啟動緩慢、在使用 3rd 方 Java 庫時調試 CLASSPATH 問題、更大的內存使用量以及現在您的代碼需要在編寫時考慮到線程安全注意事項。
此外,Ruby 的一些特性(C API,以及 Ruby 強大的自省工具之一,ObjectSpace 模塊)在 JRuby 中沒有實現。
綜上所述,對於某些情況或項目,使用 JVM 的優勢可能超過劣勢。 JVM 允許許多性能優化,例如打開 JIT 編譯器,或使用本機 Java 對象和 API。
作為一個引人注目的 JRuby 用例示例,我的一位前同事曾經遇到過一個 CPU 密集型問題,他最初使用 Ruby 1.9.3 中的線程解決了這個問題。 當他切換到 JRuby 並使用 Java 的java.util.concurrent.Executors
時,他看到此操作的性能提高了多個數量級(快了數万倍)。 在這裡查看他的實驗。
魯比紐斯
Rubinius 是 Ruby 的一個實現,它在低級虛擬機 (LLVM) 之上實現了動態語言的通用運行時。 使用這種基礎設施和 JIT 編譯器技術,Rubinius 通常可以以比 MRI 更少的開銷運行 Ruby 代碼。
Rubinius 還使用盡可能多的 Ruby 構建,以使解釋器/運行時的開發更快、更容易。

有趣的事實:RubySpec 最初是在實現 Rubinius 的過程中產生的。
與 JRuby 一樣,Rubinius 包括一個 JIT 編譯器、更好的內存管理和一個比 Ruby MRI 更成熟的虛擬機。 然而,與 JRuby 不同的是,Rubinius 支持 Ruby C 庫,並且 Rubinius 的基礎是用 C++ 編寫的,而不是 Java。
當您需要 Rails 服務器上的高性能而又沒有 JRuby 的學習曲線或其他缺點時,Rubinius 可能是一個很好的中間地帶。
姆魯比
mruby 被設計為 Ruby 的可嵌入版本(支持 Ruby 1.9.3)。 使用 mruby,您可以將 Ruby 作為原生應用程序中的腳本/自動化語言提供,將其用於遊戲腳本,甚至用於對 Raspberry Pi 等微控制器板進行編程。
如果您的平台有嚴重的資源限制,mruby 可能只是適合您的 Ruby 解釋器。 mruby 也被用於:
- 構建 iOS 應用程序(作為 RubyMotion 的競爭對手,如下所述)
- 將 Ruby 嵌入 iOS 應用程序,以提高開發速度
- 為最終用戶提供用於自動化目的的嵌入式腳本語言
隨著物聯網越來越成為現實,家庭自動化逐漸成為現實,極其便攜(且功能相對強大)的計算機越來越普遍,支持的目標平台環境也變得越來越多樣化。 mruby 有助於使用與桌面相同的高效語言來實現這一點。
蛋白石
Opal 是將 Ruby 轉換為 JavaScript 的轉譯器。
隨著 Coffeescript 的興起,開發人員了解到他們不必輸入 JavaScript 來獲取JavaScript。 雖然 Coffeescript 確實有它的優勢,但使用它的時間足夠長,你肯定會遇到你不喜歡該語言的事情。
輸入 Opal:輸入Ruby,獲取 Javascript 。 很酷。
Opal 力求與其他 Ruby 實現盡可能一致,因此也針對 RubySpec 的一個子集進行了測試。 但是,由於 JavaScript 和 JavaScript 運行時的性質,確實存在一些不兼容性。 例如,Opal 中的字符串和符號是相等的,並且 Opal 不提供任何線程或 shell 執行機制。
Opal 獨立運行或可用作 Rails 資產管道的一部分(例如,自動將somefile.js.rb
文件轉換為 JavaScript)。
也許您有一個非常適合 JavaScript 的異步並發模式的問題域(例如小型 Node.js 服務),但想要該語言或來自 Ruby 空間的某些寶石。 在這種情況下,蛋白石可能是一個很好的解決方案。
或者您可能想編寫一個完整的 Ruby Web 應用程序。 使用 Opal,您可以。 讓一個 Ruby 解釋器運行您的服務器端 Ruby 代碼,然後讓 Opal 生成 JavaScript 以在客戶端運行。
Opal 認識到您可能會與其他 JavaScript API(例如 DOM 或 Node.js)進行交互。 因此,它可以很容易地過渡到 JavaScript,並在常見的 JavaScript 庫(如 jQuery)上提供一些 Ruby 語法糖。
然而,Opal 以 JavaScript 為中心的特性既是它的優勢,也是它的劣勢。 不利的一面是,Opal 的運行時是 JavaScript 運行時,並且 Opal 受 JavaScript 設計決策的影響。 因此,如果您正在尋找一個好的 Ruby 實現來編寫一個小的 shell 腳本,或者為您的 Rails 應用程序尋找一個更好的 Ruby 運行時,Opal 可能不是您的最佳選擇。
RubyMotion
RubyMotion 既是 (a) 一個 Ruby 實現(使用 Objective-C 和 Cocoa 編寫),又是 (b) 一組語言綁定,因此開發人員可以通過 Ruby 訪問 Cocoa API。
RubyMotion 是一個商業產品,使您能夠使用 Ruby 編寫 Cocoa 原生應用程序。 RubyMotion 2.0 允許您使用 Ruby 編寫 iOS 和 Mac OS X 應用程序,而 RubyMotion 3 承諾將為 Android 帶來同樣的支持。
RubyMotion 實現了 Ruby 語言的 1.9 版。
已失效的實現
自 Ruby 首次引入以來的這些年裡,一些已經形成的 Ruby 實現已經被放棄或停止,例如:
- Ruby 企業版 (REE)。 REE 是來自 Phusion Passenger 的 MRI 1.8 的一個分支,它為 Web 開發人員實現了許多內存和垃圾收集改進。 幾年來,它是為生產 Rails 站點部署的默認 Ruby 實現。 不過,它從未針對 Ruby 1.9 或 Ruby 2.0 進行更新,並最終在 2012 年停產。
- 鐵紅寶石。 IronRuby 是在 Microsoft .NET 之上實現的 Ruby,用 C# 編寫,該項目有一段時間是由 Microsoft 資助的。 IronRuby 於 2011 年被放棄,最後一次支持 Ruby 1.8.6。
包起來
Ruby 環境中有各種各樣的運行時和解釋器可供選擇。 對於大多數 Ruby 項目,Ruby 參考實現 (Ruby MRI) 仍然是首選的解釋器。 但是,根據您的功能和技術目標和限制,替代 Ruby 實現很可能是您項目的正確選擇。
作為 Ruby 的參考實現,MRI 更快地獲得了新的語言特性,具有足夠好的並發性和內存故事(只會越來越好),並且與 gem 具有最廣泛的兼容性(一些部分是用 C 編寫的)。 總而言之,MRI 是通用 Ruby 代碼的可靠選擇。
對於更大的企業部署,或者需要與 Java 代碼(或其他 JVM 語言)交互或需要高度發展的並發模式的情況,JRuby 是一個令人信服的選擇。
當然,如果您有獨特的需求(例如,編寫 JavaScript、在當前一代的嵌入式設備上運行等等),其他 Ruby 替代品可能正是您正在尋找的。
Ruby 有多種運行時和解釋器可供選擇,Ruby 表明自己是一種靈活的語言,適用於廣泛的計算環境,從企業大型 Java 部署商店到控制辦公室紅綠燈的軟件你上週末把你的樹莓派掛了。 為正確的目的選擇正確的工具是必不可少的,是的,但希望本文向您展示了 Ruby 遠不止是您的操作系統附帶的默認 Ruby 解釋器。
隨著對語言的更改提出來,Ruby 的世界通過與核心 Ruby MRI 團隊合作的替代 Ruby 實現團隊大大增強。 他們為 Ruby 實現社區增加了多樣性,增加了他們來之不易的 Ruby 實現經驗以及他們對語言特性的看法。 Ruby 愛好者共同對這些團隊表示感謝。 為他們的努力點贊!