新闻 for Ruby 3.3.0¶ ↑
本文档列出了自 **3.2.0** 版本以来的用户可见功能变更,不包括错误修复。
请注意,每个条目都保持在最低限度,有关详细信息,请参阅链接。
命令行选项¶ ↑
-
引入了新的
performance
警告类别。即使在详细模式下,它们默认也不会显示。使用-W:performance
或Warning[:performance] = true
打开它们。[功能 #19538] -
引入了新的
RUBY_CRASH_REPORT
环境变量,允许将 Ruby 崩溃报告重定向到文件或子命令。有关更多详细信息,请参阅 ruby 手册页的BUG REPORT ENVIRONMENT
部分。[功能 #19790]
核心类更新¶ ↑
注意:我们只列出未完成的类更新。
-
-
Array#pack
现在对未知指令引发ArgumentError
。[Bug #19150]
-
-
-
Dir.for_fd
添加用于返回由提供的目录文件描述符指定的目录的Dir
对象。[Feature #19347] -
Dir.fchdir
添加用于将目录更改为由提供的目录文件描述符指定的目录。[Feature #19347] -
Dir#chdir
添加用于将目录更改为由提供的Dir
对象指定的目录。[Feature #19347]
-
-
-
Encoding#replicate
已被移除,它已被弃用。[Feature #18949]
-
-
-
引入
Fiber#kill
。[Bug #595]fiber = Fiber.new do while true puts "Yielding..." Fiber.yield end ensure puts "Exiting..." end fiber.resume # Yielding... fiber.kill # Exiting...
-
-
-
MatchData#named_captures
现在接受可选的symbolize_names
关键字。[Feature #19591]
-
-
-
Module#set_temporary_name
添加用于为模块设置临时名称。[Feature #19521]
-
-
-
新的核心类用于构建具有弱引用的集合。该类使用相等语义来查找键,就像常规哈希一样,但它不会对键保持强引用。[Feature #18498]
-
-
-
ObjectSpace::WeakMap#delete
已被添加以积极清除弱映射条目。[Feature #19561]
-
-
-
现在
Proc#dup
和Proc#clone
分别调用#initialize_dup
和#initialize_clone
钩子。[Feature #19362]
-
-
-
新的
Process.warmup
方法通知 Ruby 虚拟机引导序列已完成,现在是优化应用程序的好时机。这对于长时间运行的应用程序很有用。执行的实际优化完全是特定于实现的,并且将来可能会在未经通知的情况下更改。[Feature #18885]
-
-
-
Process::Status
#& 和Process::Status#>>
已被弃用。[Bug #19868]
-
-
-
Range#reverse_each
现在可以使用Integer
作为终点来处理无起始范围。[功能 #18515] -
Range#reverse_each
现在对于无穷范围会抛出TypeError
。[功能 #18551] -
添加了
Range#overlap?
用于检查两个范围是否重叠。[功能 #19839]
-
-
-
添加 Refinement#target 作为 Refinement#refined_class 的替代。Refinement#refined_class 已被弃用,将在 Ruby 3.4 中移除。[功能 #19714]
-
-
-
String#unpack
现在对于未知指令会抛出ArgumentError
。[Bug #19150] -
String#bytesplice
现在接受新的参数 index/length 或要复制的源字符串的范围。[功能 #19314]
-
-
-
Thread::Queue#freeze
现在会抛出TypeError
。[Bug #17146]
-
-
-
使用字符串参数的
Time.new
变得更加严格。[Bug #19293]Time.new('2023-12-20') # no time information (ArgumentError)
-
-
-
TracePoint
支持rescue
事件。当抛出的异常被捕获时,TracePoint
会触发钩子。rescue
事件只支持 Ruby 级别的rescue
。[功能 #19572]
-
标准库更新¶ ↑
-
如果用户在没有将以下 gem 添加到 Gemfile 或 gemspec 的情况下执行
require
,RubyGems 和 Bundler 会发出警告。这是因为它们将在未来版本的 Ruby 中成为捆绑的 gem。如果您使用 bootsnap gem,此警告将被抑制。我们建议您至少运行一次应用程序,并使用DISABLE_BOOTSNAP=1
环境变量。这是此版本的限制。[功能 #19351] [功能 #19776] [功能 #19843]-
abbrev
-
base64
-
bigdecimal
-
csv
-
drb
-
getoptlong
-
mutex_m
-
nkf
-
observer
-
racc
-
resolv-replace
-
rinda
-
syslog
-
abbrev
-
base64
-
bigdecimal
-
csv
-
drb
-
getoptlong
-
mutex_m
-
nkf
-
observer
-
racc
-
resolv-replace
-
rinda
-
syslog
-
-
在关闭连接时,Socket#recv 和 Socket#recv_nonblock 返回
nil
而不是空字符串。Socket#recvmsg 和 Socket#recvmsg_nonblock 在关闭连接时返回nil
而不是空数据包。[Bug #19012] -
现在可以中断诸如 Socket.getaddrinfo、Socket.getnameinfo、Addrinfo.getaddrinfo 等的名称解析。[Feature #19965]
-
Random::Formatter#alphanumeric 扩展为接受可选的
chars
关键字参数。[Feature #18183]
添加了以下默认 gem。
-
prism 0.19.0
以下默认 gem 已更新。
-
RubyGems 3.5.3
-
abbrev 0.1.2
-
base64 0.2.0
-
benchmark 0.3.0
-
bigdecimal 3.1.5
-
bundler 2.5.3
-
cgi 0.4.1
-
csv 3.2.8
-
date 3.3.4
-
delegate 0.3.1
-
drb 2.2.0
-
english 0.8.0
-
erb 4.0.3
-
error_highlight 0.6.0
-
etc 1.4.3
-
fcntl 1.1.0
-
fiddle 1.1.2
-
fileutils 1.7.2
-
find 0.2.0
-
getoptlong 0.2.1
-
io-console 0.7.1
-
io-nonblock 0.3.0
-
io-wait 0.3.1
-
ipaddr 1.2.6
-
irb 1.11.0
-
json 2.7.1
-
logger 1.6.0
-
mutex_m 0.2.0
-
net-http 0.4.0
-
net-protocol 0.2.2
-
nkf 0.1.3
-
observer 0.1.2
-
open-uri 0.4.1
-
open3 0.2.1
-
openssl 3.2.0
-
optparse 0.4.0
-
ostruct 0.6.0
-
pathname 0.3.0
-
pp 0.5.0
-
prettyprint 0.2.0
-
pstore 0.1.3
-
psych 5.1.2
-
rdoc 6.6.2
-
readline 0.0.4
-
reline 0.4.1
-
resolv 0.3.0
-
rinda 0.2.0
-
securerandom 0.3.1
-
set 1.1.0
-
shellwords 0.2.0
-
singleton 0.2.0
-
stringio 3.1.0
-
strscan 3.0.7
-
syntax_suggest 2.0.0
-
syslog 0.1.2
-
tempfile 0.2.1
-
time 0.3.0
-
timeout 0.4.1
-
tmpdir 0.2.0
-
tsort 0.2.0
-
un 0.3.0
-
uri 0.13.0
-
weakref 0.1.3
-
win32ole 1.8.10
-
yaml 0.3.0
-
zlib 3.1.0
以下捆绑 gem 从默认 gem 中提升。
-
racc 1.7.3
以下捆绑 gem 已更新。
-
minitest 5.20.0
-
rake 13.1.0
-
test-unit 3.6.1
-
rexml 3.2.6
-
rss 0.3.0
-
net-ftp 0.3.3
-
net-imap 0.4.9
-
net-smtp 0.4.0
-
rbs 3.4.0
-
typeprof 0.21.9
-
调试 1.9.1
有关默认 gem 或捆绑 gem 的详细信息,请参阅 GitHub 版本,例如 Logger 或变更日志。
Prism¶ ↑
-
引入了 Prism 解析器 作为默认 gem
-
Prism 是一个可移植的、容错的、可维护的 Ruby 语言递归下降解析器
-
-
Prism 已投入生产并积极维护,您可以将其用作 Ripper 的替代品
-
有关如何使用 Prism 的 详细文档
-
Prism 既是一个 C 库,将由 CRuby 内部使用,也是一个 Ruby gem,可供任何需要解析 Ruby 代码的工具使用
-
Prism API 中值得注意的方法是
-
Prism.parse(source)
,它将 AST 作为解析结果对象的一部分返回 -
Prism.parse_comments(source)
,它返回注释 -
Prism.parse_success?(source)
,如果没有任何错误,则返回 true
-
-
-
如果您有兴趣贡献,可以在 Prism 存储库 上直接提交拉取请求或问题
-
您现在可以使用
ruby --parser=prism
或RUBYOPT="--parser=prism"
来试验 Prism 编译器。请注意,此标志仅用于调试。
兼容性问题¶ ↑
-
通过以下文件打开方法创建/派生子进程已弃用。[功能 #19630]
-
URI.open
-
URI.open
-
当给定非 lambda、非文字块时,
Kernel#lambda
现在会引发ArgumentError
而不是返回未修改的它。这些用法自 Ruby 3.0.0 起在Warning[:deprecated]
类别下发出警告。[功能 #19777] -
RUBY_GC_HEAP_INIT_SLOTS
环境变量已弃用并已删除。应改用环境变量RUBY_GC_HEAP_%d_INIT_SLOTS
。[功能 #19785] -
在没有普通参数的块中,不带参数的
it
调用已弃用。在 Ruby 3.4 中,it
将是第一个块参数的引用。[功能 #18980] -
针对
NoMethodError
的错误消息已更改,不再使用目标对象的#inspect
以提高效率,而是显示“ClassName 的实例”。[功能 #18285]([1] * 100).nonexisting # undefined method `nonexisting' for an instance of Array (NoMethodError)
-
现在,在使用匿名参数的代码块中不允许匿名参数转发。[功能 #19370]
标准库兼容性问题¶ ↑
-
racc
已升级为捆绑的 gem。-
如果您在 bundler 环境下使用
racc
,则需要在Gemfile
中添加racc
。
-
-
ext/readline
已弃用-
我们有
reline
,它是与ext/readline
API 兼容的纯 Ruby 实现。我们将在未来依赖reline
。如果您需要使用ext/readline
,可以通过 rubygems.org 使用gem install readline-ext
安装ext/readline
。 -
我们不再需要安装
libreadline
或libedit
等库。
-
C API 更新¶ ↑
-
rb_postponed_job
更新 -
新的 API 和已弃用的 API(有关详细信息,请参阅注释)
-
新增:
rb_postponed_job_preregister()
-
新增:
rb_postponed_job_trigger()
-
已弃用:
rb_postponed_job_register()
(以及语义更改。见下文) -
已弃用:
rb_postponed_job_register_one()
-
新增:
rb_postponed_job_preregister()
-
新增:
rb_postponed_job_trigger()
-
已弃用:
rb_postponed_job_register()
(以及语义更改。见下文) -
已弃用:
rb_postponed_job_register_one()
-
-
已更改延迟作业 API 以解决一些罕见的崩溃问题。为了解决这个问题,我们引入了两个新的 API 并弃用了当前的 API。这些函数的语义也略有改变;
rb_postponed_job_register
现在与once
变体类似,即使用相同func
的多次调用可能会合并为对func
的一次执行。[功能 #20057] -
内部线程事件钩子 API 的一些更新
-
rb_internal_thread_event_data_t
带有目标 Ruby 线程 (VALUE) 和回调函数 (rb_internal_thread_event_callback
) 来接收它。 github.com/ruby/ruby/pull/8885 -
以下函数用于从内部线程事件钩子 API 操作 Ruby 线程本地数据(它们是在 Ruby 3.2 之后引入的)。 github.com/ruby/ruby/pull/8936
-
rb_internal_thread_specific_key_create()
-
rb_internal_thread_specific_get()
-
rb_internal_thread_specific_set()
-
-
rb_profile_thread_frames()
用于从特定线程获取帧。[功能 #10602] -
rb_data_define()
用于定义Data
。[特性 #19757] -
rb_ext_resolve_symbol()
用于从扩展库中搜索函数。[特性 #20005] -
IO
相关更新 -
rb_io_t
的详细信息将被隐藏,并为每个成员添加弃用属性。[特性 #19057] -
rb_io_path(VALUE io)
用于获取io
的路径。 -
rb_io_closed_p(VALUE io)
用于获取io
的打开或关闭状态。 -
rb_io_mode(VALUE io)
用于获取io
的模式。 -
rb_io_open_descriptor()
用于从文件描述符创建IO
对象。
实现改进¶ ↑
解析器¶ ↑
-
用 Lrama LALR 解析器生成器 替换 Bison。不再需要安装 Bison 从源代码构建 Ruby。我们不再受 bison 兼容性问题的影响,并且可以通过在 Lrama 中实现来使用新特性。[特性 #19637]
-
有关详细信息,请参阅 Ruby 解析器的未来愿景。
-
Lrama 内部解析器是使用 Racc 生成的 LR 解析器,以提高可维护性。
-
支持参数化规则
(?, *, +)
,它将在 Ruby parse.y 中使用。
GC
/ 内存管理¶ ↑
-
与 Ruby 3.2 相比,性能大幅提升
-
引入了一个新的
REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO
调优变量来控制导致主要GC
收集触发的未保护对象数量。默认设置为0.01
(1%)。这显著减少了主要GC
收集的频率。[特性 #19571] -
为许多缺少写屏障的核心类型实现了写屏障,特别是
Time
、Enumerator
、MatchData
、Method
、File::Stat
、BigDecimal
和其他一些类型。这显著减少了次要GC
收集时间和主要GC
收集频率。 -
现在大多数核心类都使用可变宽度分配,特别是
Hash
、Time
、Thread::Backtrace
、Thread::Backtrace::Location
、File::Stat
、Method
。这使得这些类的分配和释放速度更快,使用更少的内存,并减少堆碎片。
-
defined?(@ivar)
通过Object
形状进行了优化。
YJIT¶ ↑
-
与 Ruby 3.2 相比,性能大幅提升
-
对 splat 和 rest 参数的支持已得到改进。
-
为虚拟机的堆栈操作分配寄存器。
-
编译了更多带有可选参数的调用。
Exception
处理程序也被编译。 -
不支持的调用类型和巨型调用站点不再退出到解释器。
-
基本方法,如 Rails
#blank?
和 {专门的#present?
} 被内联。 -
Integer#*
、Integer#!=
、String#!=
、String#getbyte
、Kernel#block_given?
、Kernel#is_a?
、Kernel#instance_of?
和Module#===
已被专门优化。 -
编译速度现在比 Ruby 3.2 稍快。
-
在 Optcarrot 上比解释器快 3 倍以上!
-
与 Ruby 3.2 相比,内存使用量显著改善。
-
编译代码的元数据使用的内存更少。
-
当应用程序拥有超过 40,000 个 ISEQ 时,
--yjit-call-threshold
会自动从 30 提升到 120。 -
添加了
--yjit-cold-threshold
以跳过编译冷 ISEQ。 -
在 Arm64 上生成了更紧凑的代码。
-
-
代码
GC
现在默认情况下已禁用。 -
--yjit-exec-mem-size
被视为硬性限制,新的代码编译将在此限制下停止。 -
如果需要,您仍然可以使用
--yjit-code-gc
启用代码GC
-
添加
RubyVM::YJIT.enable
,可以在运行时启用 YJIT。 -
您可以在不修改命令行参数或环境变量的情况下启动 YJIT。Rails 7.2 将 默认启用 YJIT,使用此方法。
-
这也可以用于仅在应用程序启动完成后启用 YJIT。如果您想在启动时禁用 YJIT,但使用其他 YJIT 选项,则可以使用
--yjit-disable
。 -
默认情况下,更多 YJIT 统计信息可用。
-
yjit_alloc_size
和其他几个与元数据相关的统计信息现在默认情况下可用。 -
--yjit-stats
生成的ratio_in_yjit
统计信息现在在发布版本中可用,不再需要特殊的统计信息或开发版本来访问大多数统计信息。 -
添加更多分析功能。
-
添加
--yjit-perf
以便于使用 Linux perf 进行分析。 -
--yjit-trace-exits
现在支持使用--yjit-trace-exits-sample-rate=N
进行采样。 -
更全面的测试和多个错误修复。
-
--yjit-stats=quiet
已添加以避免在退出时打印统计信息。
MJIT¶ ↑
-
MJIT 已移除。
-
--disable-jit-support
已移除。请考虑使用--disable-yjit --disable-rjit
代替。
-
RJIT¶ ↑
-
引入了纯 Ruby JIT 编译器 RJIT。
-
RJIT 仅支持 Unix 平台上的 x86_64 架构。
-
与 MJIT 不同,它在运行时不需要 C 编译器。
-
-
RJIT 仅用于实验目的。
-
您应该在生产环境中继续使用 YJIT。
-
M:N Thread
调度器¶ ↑
-
引入了 M:N
Thread
调度器。[Feature #19842]-
背景:Ruby 1.8 及更早版本使用 M:1 线程调度器(M 个 Ruby 线程与 1 个原生线程。称为用户级线程或绿色线程)。Ruby 1.9 及更高版本使用 1:1 线程调度器(1 个 Ruby 线程与 1 个原生线程)。与 1:1 线程相比,M:1 线程占用更少的资源,因为它只需要 1 个原生线程。但是,很难为所有阻塞操作提供上下文切换支持,因此从 Ruby 1.9 开始使用 1:1 线程。M:N 线程调度器为 M 个 Ruby 线程使用 N 个原生线程(通常 N 是一个小数字)。它不需要与 Ruby 线程数量相同的原生线程(类似于 M:1 线程调度器)。此外,我们的 M:N 线程与 1:1 线程一样,也很好地支持阻塞操作。有关更多详细信息,请参阅该问题。我们的 M:N 线程调度器参考了 Go 语言中的 goroutine 调度器。
-
在 ractor 中,由于实现原因,同一时间只能运行 1 个线程。因此,仅使用一个
Ractor
的应用程序(大多数应用程序)M:N 线程调度器将作为 M:1 线程调度器工作,并从 Ruby 1.8 开始进一步扩展。 -
M:N 线程调度器可能会引入 C 扩展的不兼容性,因此在主 Ractor 上默认情况下禁用它。
RUBY_MN_THREADS=1
环境变量将启用它。在非主 Ractor 上,M:N 线程调度器已启用(并且现在无法禁用它)。 -
N
(原生线程数量)可以使用RUBY_MAX_CPU
环境变量指定。默认值为 8。请注意,使用超过N
个原生线程来支持多种阻塞操作。
-