Ruby 2.6.0 正式版已经发布,引入了许多新功能和性能改进,最值得关注的有亮点:
- 新的 JIT 编译器
- RubyVM::AbstractSyntaxTree 模块
JIT [实验]
Ruby 2.6 引入了 JIT (Just-in-time) 编译器实现。
JIT 编译器旨在提高 Ruby 性能。与其他语言的普通 JIT 编译器不同,Ruby 的 JIT 编译器以一种独特的方式进行 JIT 编译,它先将 Ruby 编译成 C 代码,然后通过生成通用的 C 编译器过程 (compiler process) 来生成原生机器码。详情可查阅 Vladimir Makarov 的 MJIT 组织 。
要启用 JIT 编译器,在命令行或 $RUBYOPT
环境变量中指定 --jit
参数即可。
在一个名叫 Optcarrot 的 CPU 密集计算基准测试中,Ruby 2.6 与 Ruby 2.5 相比,性能提高了 1.7 倍。不过目前仍然处于试验阶段,详见 Ruby 2.6 JIT - 进程与未来。
请保持对 Ruby 新时代性能的关注。
RubyVM::AbstractSyntaxTree [实验]
Ruby 2.6 引入了 RubyVM::AbstractSyntaxTree
模块,此模块向后兼容性不做保证。
**
此模块提供一个 parse
方法,传入 Ruby 代码字符串,返回 AST(抽象语法树)节点。而 parse_file
方法则接受一个 Ruby 代码文件作为参数,返回 AST 节点。
同时引入了 RubyVM::AbstractSyntaxTree::Node
类,你可以从 Node
对象中获取位置信息和子节点。此功能尚处于实验性质。
其它新特性
Kernel#yield_self
添加新别名then
。[Feature #14594]- 常量名现在可以以非 ASCII 大写字母开头。[Feature #13770]
- 无限范围 [Feature #12912]
引入了无限范围(1..)
。这个范围没有终点,以下是使用场景的举例。
ary[1..] # 等价于 ary[1..-1] 而不需要魔法 -1
(1..).each {|index| ... } # 从 1 开始无限循环
ary.zip(1..) {|elem, index| ... } # ary.each.with_index(1) { ... }
- 新增
Enumerable#chain
与Enumerator#+
[Feature #15144] - 为
Proc
和Method
新增了函数构造操作符<<
与>>
。 [Feature #6284]
f = proc{|x| x + 2}
g = proc{|x| x * 3}
(f << g).call(3) # -> 11; identical to f(g(3))
(f >> g).call(3) # -> 15; identical to g(f(3))
- 新增
Binding#source_location
。[Feature #14230] - 此方法以一个二元组数组
__FILE__
和__LINE__
的形式返回 binding 的源代码路径。传统上,这可以通过执行eval("[__FILE__, __LINE__]", binding)
来获得相同的数据。但我们计划改变这一行为让Kernel#eval
忽略binding
的源代码路径 [Bug #4352]。所以,用户需要通过新加入的方法来替代之前的Kernel#eval
。 - 增加
:exception
选项,以让Kernel.#system
抛出错误而不是返回false
。[Feature #14386] - 新增 oneshot 模式 [Feature #15022]
- 此模式检查「每一行代码是否都至少被执行一次」,而不是「每行代码被执行了几次」。每行代码的 hook 至多被调用一次,并会在调用后将 hook 标识移除。换句话说,移除后的代码运行将没有额外的性能开销。
- 为
Coverage.start
方法新增:oneshot_lines
关键字参数。 - 为
Coverage.result
方法新增:stop
和:clear
关键字参数。如果clear
被设置为 true,它会清空计数器。如果stop
被设置为 true,它会禁用覆盖测量。 - 新增
Coverage.line_stub
,其为从源代码新建代码覆盖存根(stub)提供了一个简单的帮助函数。
FileUtils#cp_lr
。[Feature #4189]
性能提升
通过 lc_fizzbuzz
多次使用 Proc#call
的 benchmark 我们测量到了 1.4 倍性能提升 [Bug #10212]。
通过与 Ruby 2.5 中引入的提升代码块传递的性能的方法结合,Ruby 2.6 进一步提升了传递代码块调用时的性能。通过 micro-benchmark 测试有 2.6 倍性能提升。[Feature #14045]
瞬态堆是用于管理指向特定类(Array、Hash、Object 和 Struct)短生命周期内存对象的堆。例如,创建小而短生命周期的哈希对象的速度提升到了 2 倍快。根据 rdoc benchmark,我们观察到了 6% 到 7% 的性能提升。
- 协程采用了原生实现(
arm32
、arm64
、ppc64le
、win32
、win64
、x86
、amd64
)显著提升了 Fiber 的性能。 [Feature #14739]
Fiber.yield
与 Fiber#resume
方法在 64 位 Linux 上提升了 5 倍性能。对于使用 Fiber 密集的程序,约有最高 5% 的性能提升。
其它自 2.5 以来值得注意的新特性
$SAFE
成为了进程全局状态,我们可以再次将其设为0
。[Feature #14250]- 不再建议将
safe_level
参数传递给ERB.new
的行为。trim_mode
和eoutvar
参数被转换成了关键词参数。[Feature #14256] - 升级支持的 Unicode 版本至 11。我们计划在未来 Ruby 2.6 的小更新中升级至 12 和 12.1。其将引入新的日本年号。
- 合并 RubyGems 3.0.1,
--ri
和--rdoc
选项已被移除。请使用--document
和--no-document
选项来替代他们。 - 合并 Bundler 作为默认 gem 安装。
- 不含
rescue
的else
现在会引起语法错误。[实验性][Feature #14606]
随着这些变动,自 Ruby 2.5.0 已发生了 6437 个文件变更,231471 行新增(+),98498 行删除(-)!
圣诞快乐!享受你 Ruby 2.6 的编程之旅吧!
原文连接:https://www.ruby-lang.org/en/news/2018/12/25/ruby-2-6-0-released/