Ruby 创始人 Yukihiro Matsumoto,也就是 Matz,在 GitHub 上放出了 Spinel。它是一个实验性 Ruby AOT 编译器:把 Ruby 源码编译成独立原生二进制文件,运行时不依赖 Ruby,只需要 libc 和 libm。

项目 README 给出的数字很亮:74 个测试通过,55 个基准通过。在其中 28 个计算型 benchmark 上,Spinel 相比 Ruby 4.1.0dev 的 miniruby,几何平均约快 11.6 倍。GitHub 页面显示 414 stars,许可证是 MIT。

但别把它读成 CRuby 的替代路线。现有材料只能说明:这是 Matz 个人 GitHub 上的实验项目。它很有价值,也很有边界。

Spinel 做了什么:Ruby 先变 AST,再变 C,最后变原生二进制

Spinel 的编译链路不绕。

Ruby 源码先由 Prism 解析成 AST,再由 spinel_codegen.rb 做全程序类型推断和 C 代码生成,最后交给 cc -O2 编译成原生二进制。

后端本身用 Ruby 写。更关键的是,它已经能自举:Spinel 可以编译自己的后端。这说明它不是只会跑几个演示程序的小脚本。

维度Spinel 当前状态该怎么理解
编译流程Ruby → Prism AST → 类型推断/C 代码生成 → cc 原生二进制走 AOT 原生化路线
运行依赖不依赖 Ruby 运行时,只需 libc 和 libm有利于单文件分发和嵌入式部署
性能数字计算型 benchmark 几何平均约 11.6x 快于 miniruby不能外推到 Rails、Gem 生态和真实 Web 服务
已覆盖能力类、块、异常、Regexp、Bigint、Fiber、GC 等Ruby 子集已经有实用雏形
明确缺失eval、send、method_missing、动态 define_method、线程、编码等这些不是小功能,是 Ruby 动态生态的硬骨头

性能来源也不神秘。

Spinel 依靠全程序类型推断、值类型栈分配、短方法内联、字符串拼接优化、死代码消除等手段提速。比如,小型不可变类可以提升成 C struct 放到栈上;a + b + c + d 这类字符串拼接可以合并分配;不用的 runtime 函数可以被链接器剔掉。

所以,这不是“Ruby 突然变快了”。更准确的说法是:Ruby 被放进了一个更窄、更可分析、更适合编译器下手的盒子里。

这对开发者的动作影响很具体。

写 Ruby CLI 工具、内部运维脚本、边缘设备脚本的人,可以开始观察 Spinel 能不能跑自己的小程序。不要急着迁移业务代码。先拿无外部依赖、少元编程、偏计算的脚本试编译。

Rails 团队和重度 Gem 用户则应该观望。现在拿 Spinel 评估 Rails 性能,基本是在问错问题。

它快在哪里:不是替代 CRuby,而是撕开高性能 Ruby 子集

Ruby 过去的性能路线,主战场更多在解释器、JIT 和替代运行时上。YJIT 改的是 CRuby 里的执行效率;TruffleRuby 更偏完整运行时与 GraalVM 生态;Ruby Packer、PyInstaller、Nuitka 这类工具更常被拿来讨论分发形态或静态编译。

Spinel 的味道不一样。它直接选择 AOT,直接生成原生二进制,也直接付出动态能力缩水的代价。

路线主要目标现实约束
CRuby / YJIT在主流 Ruby 生态内提升运行效率仍要背负大量动态语义和兼容包袱
TruffleRuby用替代运行时争取高性能和生态能力部署、兼容、运行环境都有门槛
打包工具让脚本更容易分发不等于真正把语言语义编译成高性能原生代码
Spinel通过 AOT 和全程序分析生成原生二进制必须收窄 Ruby 动态特性

这就是 Spinel 最硬的地方:它没有假装免费午餐。

想要 AOT,想要单文件,想要更接近 C/Go/Rust 那种部署体验,就不能同时带着 evalmethod_missing、动态 define_method 和线程等复杂语义到处跑。

“鱼与熊掌不可得兼。”这句老话放在动态语言上很准。自由、性能、生态兼容,三者很难一起满分。Ruby 的表达力越强,编译器要证明的东西就越多;编译器越想激进优化,就越需要程序边界清楚。

这也是为什么 Spinel 的 benchmark 要谨慎读。

它跑赢的是一批可被全程序分析理解的计算型程序。真实 Ruby 应用常常不是这样长的。Rails、DSL、运行期改类、动态派发、Gem 组合,才是很多 Ruby 项目的日常骨架。

Spinel 的胜利,暂时属于“可编译的 Ruby”。不是整个 Ruby 世界。

接下来该看什么:别数 star,盯边界

414 stars 能说明开发者有兴趣,不能说明生态已经形成。实验项目最容易被误读的地方,就是把一次漂亮演示当成生产路线。

更该盯的是四个变量。

  • 可编译 Ruby 子集能不能扩大,尤其是常见标准库和常见写法。
  • Gem 边界能不能清楚,不求全吃,但要知道哪些能吃、哪些会卡死。
  • 错误栈、调试体验、跨平台行为能不能让人放心接进工具链。
  • 性能收益能不能在计算型 benchmark 之外保住,而不是只在小程序里好看。

对技术决策者来说,合理动作不是“迁移到 Spinel”。现在还不到那个阶段。

更现实的动作是建一个小清单:哪些 Ruby 脚本没有元编程、没有线程依赖、没有复杂编码处理、依赖少、计算重、分发麻烦。这样的脚本可以试编译。编不过,就记录缺口;编得过,再看启动、体积、性能和调试成本。

对 Ruby 工具作者来说,Spinel 给了一个新方向:如果你的工具本来就是命令行程序,且逻辑边界清楚,未来也许可以多写一点“可 AOT 的 Ruby”。这不是为了讨好编译器,而是为了换部署收益。

我不太买账“Ruby 终于要靠 AOT 翻身”这种说法。Ruby 的问题从来不只是速度。它的魅力和负担都在动态性里。

Spinel 真正有意思的地方,是它承认代价。它不承诺把 Rails 世界原样搬进原生二进制。它只是在说:有一类 Ruby 程序,可以少要一点自由,多换一点速度和分发确定性。

这比喊口号诚实得多。