30 周年之际,Ruby 语言带着全新的 4.0 版本,给开发者送上了年终大礼。
新增隔离命名空间、新的 JIT 编译器,还有重设计的Ractor API,这款开源语言迎来一系列更新。
Ruby 是一种开源的面向对象脚本语言,在 20 世纪 90 年代由日本人松本行弘开发,遵守 GPL 协议和 Ruby License。
其主要特性就是简单快捷,变量没有类型、任何东西都有值,不需要注释就可以读懂。
对于这次更新,网友们给予了高度评价,表示要是没有 Ruby 更新,连圣诞节都不完整了。
那么,30 岁的 Ruby,这次都迎来了哪些更新呢?
全新编译器 ZJIT
Ruby 4.0 中,Rails at Scale 团队正式推出了名为ZJIT的全新即时编译器(Just-In-Time Compiler)。
这是一种一种传统的方法级编译器,核心架构采用了静态单赋值(SSA,Static Single Assignment)形式的中间表示,旨在突破现有 YJIT 编译器的性能上限。
传统的 Ruby 解释器是逐行执行代码,效率较低,而 JIT 编译器则是将热点代码转换成机器码。
其中,YJIT 的设计理念聚焦于局部,它将编译视域限制在微小的基本块(Basic Block)中。
这种策略虽然能快速生成机器码并降低内存占用,但由于缺乏对代码整体结构的认知,难以进行跨越整个方法的全局优化。
相对而言,ZJIT 引入了SSA 中间表示技术。在这种架构下,编译器会分析完整的方法体并构建全局数据流图,确保每个变量在逻辑上仅被赋值一次。
这种全局分析能力赋予了 ZJIT 执行常量折叠(在编译期直接计算固定结果)和死代码消除(移除无效计算步骤)等深度优化的潜力,这些都是 YJIT 受限于架构而难以高效实现的。
在处理 Ruby 的动态类型特性时,两者也采用了截然不同的路径。
YJIT 倾向于通过版本化机制保留多条代码路径以适应不同的变量类型。
ZJIT 则采用了侧向退出(Side-exits)机制。
它会基于当前类型稳定的假设生成单一且激进优化的机器码,一旦运行时检测到变量类型不再符合预期(例如整数变为字符串),程序会立即触发侧向退出,终止当前优化代码的执行并安全回退到解释器。
这种机制允许编译器在假设成立的前提下剥离大量冗余检查。
尽管 ZJIT 目前的综合性能尚未完全超越成熟的 YJIT,但其基于 SSA 的严谨架构可以突破局部优化带来的瓶颈,为 Ruby 在未来实现更复杂的代码分析和更高的峰值性能奠定了基础。
隔离命名空间 Ruby::Box
Ruby::Box 是一个专门用于隔离代码执行环境的容器类,目的是解决长期困扰 Ruby 开发者的 " 全局污染 " 问题,并为构建更安全、模块化的应用提供原生支持。
这涉及到 Ruby 的一个核心特性——开放类(Open Class)。
在传统的 Ruby 环境中,任何代码都可以随时修改系统内置的类(例如给 String 类添加新方法),这种行为被称为 " 猴子补丁 "(Monkey Patching)。
虽然这种特性赋予了语言极大的灵活性,但在大型项目中,如果不同的第三方库同时修改了同一个类,就会引发严重的命名冲突。
Ruby::Box 通过彻底的命名空间隔离(Namespace Isolation)解决了这一难题。
当代码在某个 Box 中运行时,它对内置类的修改、定义的全局变量或顶层常量,都被严格限制在当前 Box 的内部作用域中,完全不会 " 泄漏 " 到外部环境或其他 Box 中。
从架构设计的角度来看,Ruby::Box 被定义为 Module 的子类,这意味着它本质上也是一种模块。
在 Ruby4.0 的运行模型中,所有的用户主程序默认运行在名为 "main" 的 Box 中。而当开发者通过 Ruby::Box.new 创建新的隔离环境时,系统会基于包含最原始、纯净 Ruby 环境的 "root"Box 进行复制。
为了确保高性能,这一过程采用了写时复制(Copy-on-Write)技术,这使得创建新 Box 的内存开销极低,同时保证了各个环境之间的独立性。
此外,Ruby::Box 还提供了文件级的作用域控制能力。通常情况下,一个 .rb 文件的加载和执行可以被限定在一个单一的 Box 中,这意味着该文件内的所有方法定义和常量解析都在该 Box 的上下文中完成。
这对于开发插件系统、多租户应用或者需要运行不可信代码(沙箱环境)的场景具有革命性意义。它允许开发者在保留 Ruby 动态特性的前提下,构建出更加健壮、安全且易于维护的系统架构。
重设计的 Ractor API
在 Ruby4.0 的更新中,为了解决 Ruby3.x 时代 Ractor 通信中存在的 " 多路通信混乱 " 和 " 消息窃取 " 等诸多痛点,Ractor API 也迎来了一次重大的重构。
其核心在于引入了Ractor::Port机制,让并行编程变得更加直观和安全。
在早期版本中,Ractor 主要依赖 " 推 "(Push)和 " 拉 "(Pull)两种模式。当多个 Ractor 向同一个目标发送消息时,接收方往往难以分辨消息的来源,就像所有信件都被塞进了一个没有标签的公共邮箱。
而在新版设计中,Ractor::Port 充当了专用信道的角色,任何人都可以向这个端口发送消息,但只有端口的创建者才有权从里面取出消息。这种 " 多对一 " 的单向通道设计,完美契合了 Actor 模型的语义。
具体的改进主要体现在三个方面:
首先是消息的定向投递与安全性。通过 Ractor::Port,消息不再是广播式的混乱投递,而是精准地发送到指定的端口。这彻底杜绝了 " 消息窃取 " 现象,即 A 模块发送的消息意外被 B 模块的接收函数截获。
其次是摒弃了复杂的同步原语。新版本废弃了 Ractor.yield 和 Ractor,转而使用更清晰的 Ractor。
同时,为了处理 Ractor 的生命周期,引入了与线程类似的 Ractor(等待结束)和 Ractor(获取返回值)方法。
特别是 Ractor,它设计为只能被一个 Ractor 调用一次,这种限制允许系统在不复制对象的情况下安全地传递返回值,极大地提升了效率。
最后是高效的多路复用。新的 Ractor.select 方法经过重写,现在支持同时监听多个 Ractor::Port。
当任何一个端口收到消息时,select 会立即返回该端口和对应的消息。这比传统的轮询机制要高效得多,并且解决了过去在复杂并发场景下难以协调多个数据源的问题。
总的来说,Ractor::Port 的引入通过更轻量级的实现和更严谨的通信契约,为 Ruby 开发者提供了一套既符合直觉又具备高性能的并发工具箱。
其他更新
除了上面三个比较大的方面,这次 Ruby 4.0 还有一系列其他更新:
语法更符合直觉:逻辑运算符现在可以写在换行后的行首,不再强制要求放在上一行行末;
核心库 " 转正 ":Set 和 Pathname 从标准库升级为核心库,开发者无需再手动编写 require 语句;
调试体验升级:当发生参数传递错误时,ErrorHighlight 功能现在不仅会高亮显示 " 调用出错 " 的代码行,还会同时显示 " 方法定义 " 的代码行,方便开发者快速对照排查;
紧跟 Unicode 标准:完整支持 Unicode17.0 标准,能原生识别和处理最新的 Emoji17.0 表情符号;
更严格的空值检查:为了防止空值意外转换成空数组从而掩盖代码逻辑中的 Bug,nil 对象不再响应 to_a 方法;
性能底层优化:Class.new(创建新类)的速度在所有场景下都得到了显著提升;垃圾回收机制(GC)现在能独立管理不同大小的内存池,有效降低了内存占用;
更灵活的数组查询:Array 类新增了 rfind 方法,可以高效地从数组末尾开始向前查找符合条件的元素;
自定义对象展示:Kernel,开发者可以通过定义 instance_variables_to_inspect 来决定在打印对象调试信息时显示哪些变量,避免输出过多无关信息。
那么,你觉得更新后的 Ruby,有没有更好用呢?
参考链接:
[ 1 ] https://www.ruby-lang.org/en/news/2025/12/25/ruby-4-0-0-released/
[ 2 ] https://docs.ruby-lang.org/en/master/Ruby/Box.html
[ 3 ] https://railsatscale.com/2025-12-24-launch-zjit/
[ 4 ] https://dev.to/ko1/ractorport-revamping-the-ractor-api-98
一键三连「点赞」「转发」「小心心」
欢迎在评论区留下你的想法!
— 完 —
专属 AI 产品从业者的实名社群,只聊 AI 产品最落地的真问题 扫码添加小助手,发送「姓名 + 公司 + 职位」申请入群~
进群后,你将直接获得:
最新最专业的 AI 产品信息及分析
不定期发放的热门产品内测码
内部专属内容与专业讨论
点亮星标
科技前沿进展每日见


登录后才可以发布评论哦
打开小程序可以发布评论哦