【问题标题】:What kind of interpreter is the Ruby MRI?Ruby MRI 是一种什么样的解释器?
【发布时间】:2026-02-15 17:30:02
【问题描述】:

它是语言解释器吗?还是字节码解释器/JIT 编译器?我在哪里可以了解更多关于实现的信息(除了浏览源代码)?

【问题讨论】:

    标签: ruby implementation interpreter


    【解决方案1】:

    注意:“MRI”一词令人困惑。它的意思是“Matz 的 Ruby/参考实现/解释器”。但是,MRI 已经退役,不再开发或维护。

    MRI 是一个纯 AST-walking 解释器,不涉及任何编译。

    令人困惑的是:Matz 编写了一个新的实现,但它叫做 MRuby,而不是 MRI。而现在称为 MRI 的实现并不是由 Matz 编写的。因此,实际上,最好根本不使用该术语,并具体说明您正在谈论的实现。

    现在人们称之为 MRI 的实现名称实际上是 YARV(代表 Yet Another Ruby VM),它是由 Koichi Sasada 编写的。它由一个将 Ruby 源代码编译为 YARV 字节码的 Ahead-Of-Time 编译器和一个解释所述字节码的解释器组成。因此,它是一个完全典型的字节码 VM,与 Python 的 CPython、PHP 的 Zend Engine、Lua VM、Rubinius 的旧版本、ECMAScript 的 SpiderMonkey 的旧版本等完全一样。

    关于将 YARV 字节码的 JIT 编译器添加到 YARV 3 的本机机器代码到 VM 的讨论,这将使 VM 成为混合模式执行引擎。

    Matz 当前的实现 MRuby 也是一个字节编码的 VM。

    为了完整起见,这里有几个其他的 Ruby 实现,首先是当前可用于生产的实现,然后是几个历史上有趣的实现:

    • Rubinius:提前将 Ruby 源代码编译为 Rubinius 字节码,然后将该字节码交给由字节码解释器和基于 LLVM 的 JIT 编译器组成的混合模式执行引擎;他们最近引入或正在为 JIT 编译器引入单独的中间表示 (IR),因此解释器使用 Rubinius 字节码,但 JIT 编译器使用 Compiler IR。 Rubinius 也属于“具有历史意义的”类别,因为它是第一个成功的 Ruby 实现,其中很大一部分是用 Ruby 实现的。之前也有其他项目,但 Rubinius 是第一个准备好生产的项目。
    • JRuby:主模式是一个混合模式执行引擎,由一个 AST-walking 解释器和一个 JIT 编译器组成,该编译器首先将 AST 转换为 IR,然后将其进一步编译为 JVM 字节码。另一种模式是 AOT 编译器,它将 Ruby 源代码提前编译为 JVM 字节码。
    • Opal:将 Ruby 源代码编译为 ECMAScript 源代码的 Ahead-Of-Time 编译器。
    • MagLev:基于 GemStone/S Smalltalk VM 的实现。不幸的是,我对此了解不多,我相信它将 Ruby 源代码编译为 GemStone/S 字节码,GemStone/S VM 是标准的混合模式 VM,带有字节码解释器和 JIT 编译器。

    一些不再维护但历史上有趣的实现:

    • Topaz:使用 RPython/PyPy VM 框架的实现; PyPy 框架很有趣,因为它包含一个跟踪 JIT 编译器,与其他 JIT 编译器不同,它不工作除了解释器并编译用户程序,而是编译 解释器,而它正在解释用户程序。这基本上意味着 JIT 只需由 PyPy 开发人员编写一次,每个使用 PyPy 框架的语言实现者只需编写一个简单的字节码解释器即可免费获得优化的原生 JIT 编译器。
    • XRuby:第一个用于 Ruby 的静态 AOT 编译器,为 JVM 实现。
    • IronRuby:它最初是一个没有解释器的纯 JIT 编译器,但后来添加了一个解释器,因为事实证明这实际上提高了性能(这与解释器的流行神话相反很慢)。
    • unholy:一个概念验证的 AOT 编译器,将 YARV 字节码编译为 CPython 字节码;当 Google App Engine 刚出现并且只支持 Python 时,这被 _why the lucky hard 破解了,这个想法是你可以使用 YARV 将 Ruby 源代码编译为 YARV 字节码,使用 unholy 将 YARV 字节码编译为 CPython 字节码,编译使用 decompyle 将 CPython 字节码转换为 Python 源代码,然后将 Python 源代码上传到 GAE 以运行您闪亮的新 Ruby 应用程序。
    • 荣誉奖:tinyrb、metaruby、Ruby.NET、Red Sun、HotRuby、BlueRuby、SmallRuby

    目前有几个有趣的研究项目是:

    • JRuby+Truffle:该项目使用 Oracle Labs 的 Truffle AST 解释器框架重新实现 JRuby 的内部;此版本在支持 Graal 的 JVM(另一个 Oracle 实验室研究项目)上运行时,能够获得与 Java 相似的性能,有时甚至达到(并超过)C。
    • Ruby+OMR:IBM 已将其 J9 JVM 分解为可独立重用、独立于语言的构建块,供 VM 实现者使用,并在 Eclipse 保护伞下作为 Eclipse Open Managed Runtime 在开源许可下发布。这不是一个学术项目:IBM J9 的 Java 8 版本实际上是使用 OMR 实现的。 Ruby+OMR 项目是 OMR 开发人员的概念验证,用 OMR 替换 YARV 的垃圾收集器,并将 OMR 的 JIT 编译器、分析器和调试器添加到 YARV。令人印象深刻的是 所有的东西实际上是独立于语言的,整个补丁不到 10000 行,这不仅仅是胶水代码,它实际上 包含所有必需的 OMR 组件。 (还有一个等效的 Python+OMR 项目,但它仍然是非公开的。)

    最后但并非最不重要的一点是,您有时可能会听说“Rite”。十多年来,Rite 一直被用作完全重写 MRI 的代号。 Matz 说,当他编写 MRI 时,他实际上对语言实现一无所知,所以他想第二次“正确”地做(明白了吗?)。同时,也有很多关于 Ruby 2.0 的讨论,希望修复该语言中一些长期存在的设计缺陷。两者混为一谈,因此 Rite 被称为 Ruby 2.0 的新实现。然而,YARV 出现并且非常好,以至于 Matz 认为他根本不需要编写自己的 VM,他基本上认为“YARV 就是 Rite”。

    但现在,他确实编写了自己的 VM,这就是为什么您有时会听到 MRuby(或其 VM 组件)被称为“Rite”的原因。

    【讨论】:

      【解决方案2】:

      这是一个名为YARV 的字节码解释器,由 Sasada Koichi 编写。

      这是一个外观示例:

      puts RubyVM::InstructionSequence.compile("1+1").disasm
      == disasm: #<ISeq:<compiled>@<compiled>>================================
      0000 trace            1                                               (   1)
      0002 putobject_OP_INT2FIX_O_1_C_
      0003 putobject_OP_INT2FIX_O_1_C_
      0004 opt_plus         <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>
      0007 leave
      

      进一步阅读:

      虽然 MRI 还没有 JIT,但有一个 Ruby+OMR 项目,它正在尝试添加一个基于 Eclipse OMR 的 JIT 编译器:

      【讨论】:

      • 哇!非常有意思!我不知道它可以从语言本身内部获得。
      • 我刚刚为您添加了更多信息 :-)
      • 我还是不明白字节码解释器和 JIT 编译器有什么区别。刚刚在软件工程中问了一个关于它的问题。感谢您的回答!
      • @user6245072:关键的区别很简单:解释器执行程序。编译器将程序从一种语言翻译成另一种语言。 AOT 与 JIT 是指编译发生的时间:提前是在运行时之前,即时是在运行时。
      【解决方案3】:

      Ruby 现在有一个由 VM 生成的 JIT 编译器!

      自从 2.6.0-preview1 分支合并后,Ruby 现在有了一个名为“MJIT”(YARV MRI Jit)的基本 JIT 编译器。它的灵感来自 Vladimir Makarov 的作品,他提出了基于 RTL(寄存器传输语言)的指令集,而不是基于堆栈的指令集。加速尚不明显,因为并非所有指令路径都由 MJIT 处理,但分支包含未来工作的基础。

      【讨论】: