Ruby 2.6.0 发布

Ruby 2.6.0 正式版已经发布,引入了许多新功能和性能改进,最值得关注的有亮点:git

  • 新的 JIT 编译器
  • RubyVM::AbstractSyntaxTree 模块

JIT [实验]

Ruby 2.6 引入了 JIT (Just-in-time) 编译器实现。github

JIT 编译器旨在提升 Ruby 性能。与其余语言的普通 JIT 编译器不一样,Ruby 的 JIT 编译器以一种独特的方式进行 JIT 编译,它先将 Ruby 编译成 C 代码,而后经过生成通用的 C 编译器过程 (compiler process) 来生成原生机器码。详情可查阅 Vladimir Makarov 的 MJIT 组织编程

要启用 JIT 编译器,在命令行或 $RUBYOPT 环境变量中指定 --jit 参数便可。c#

在一个名叫 Optcarrot 的 CPU 密集计算基准测试中,Ruby 2.6 与 Ruby 2.5 相比,性能提升了 1.7 倍。不过目前仍然处于试验阶段,详见 Ruby 2.6 JIT - 进程与将来数组

请保持对 Ruby 新时代性能的关注。ruby

RubyVM::AbstractSyntaxTree [实验]

Ruby 2.6 引入了 RubyVM::AbstractSyntaxTree 模块,此模块向后兼容性不作保证。ide

此模块提供一个 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]

此方法以一个二元组数组 FILELINE 的形式返回 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]

性能提高

  • 因为移除了对 $SAFE 临时赋值的支持,提高 Proc#call 的速度。[Feature #14318]
  • 经过 lc_fizzbuzz 屡次使用 Proc#call 的 benchmark 咱们测量到了 1.4 倍性能提高 [Bug #10212]。
  • 提高了当 block 是代码块参数时 block.call 的性能。[Feature #14330]

经过与 Ruby 2.5 中引入的提高代码块传递的性能的方法结合,Ruby 2.6 进一步提高了传递代码块调用时的性能。经过 micro-benchmark 测试有 2.6 倍性能提高。[Feature #14045]

  • 引入了瞬态堆 (theap)。 [Bug #14858] [Feature #14989]

瞬态堆是用于管理指向特定类(Array、Hash、Object 和 Struct)短生命周期内存对象的堆。例如,建立小而短生命周期的哈希对象的速度提高到了 2 倍快。根据 rdoc benchmark,咱们观察到了 6% 到 7% 的性能提高。

  • 协程采用了原生实现(arm3二、arm6四、ppc64le、win3二、win6四、x8六、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 如今会引发语法错误。实验性

更多详情见 NEWS 或 提交日志 以查看详情。

随着这些变更,自 Ruby 2.5.0 已发生了 6437 个文件变动,231471 行新增(+),98498 行删除(-)

圣诞快乐!享受你 Ruby 2.6 的编程之旅吧!

相关文章
相关标签/搜索