Ruby 3.3.0 的 NEWS¶ ↑
本文档列出了自 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
对象。 [特性 #19347] -
添加了
Dir.fchdir
,用于将目录更改为由提供的目录文件描述符指定的目录。 [特性 #19347]
-
-
-
Encoding#replicate
已被删除,它已被弃用。 [特性 #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
关键字。 [特性 #19591]
-
-
-
添加了
Module#set_temporary_name
,用于设置模块的临时名称。 [特性 #19521]
-
-
-
用于构建具有弱引用的集合的新核心类。该类使用相等语义来查找键,就像常规哈希一样,但它不持有键的强引用。 [特性 #18498]
-
-
-
添加了
ObjectSpace::WeakMap#delete
以积极清除弱映射条目。 [特性 #19561]
-
-
-
现在
Proc#dup
和Proc#clone
分别调用#initialize_dup
和#initialize_clone
钩子。 [特性 #19362]
-
-
-
新的
Process.warmup
方法,通知 Ruby 虚拟机启动序列已完成,现在是优化应用程序的好时机。这对于长时间运行的应用程序很有用。执行的实际优化完全取决于具体实现,并且可能会在未来更改,恕不另行通知。 [特性 #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
现在接受新参数,即要复制的源字符串的索引/长度或范围。 [特性 #19314]
-
-
-
Thread::Queue#freeze
现在会引发TypeError
。 [Bug #17146]
-
-
-
Thread::SizedQueue#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 等,现在可以中断。 [特性 #19965]
-
Random::Formatter#alphanumeric 扩展为接受可选的
chars
关键字参数。 [特性 #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
-
debug 1.9.1
有关默认 gem 或捆绑 gem 的详细信息,请参阅 GitHub 版本,例如 Logger 或更新日志。
Prism¶ ↑
-
引入 Prism 解析器 作为默认 gem
-
Prism 是一个可移植、容错且可维护的 Ruby 语言递归下降解析器
-
-
Prism 已准备好用于生产,并积极维护,您可以将其代替 Ripper 使用
-
有关如何使用 Prism 的大量文档
-
Prism 既是一个将由 CRuby 内部使用的 C 语言库,也是一个 Ruby gem,可供任何需要解析 Ruby 代码的工具使用。
-
Prism API 中值得注意的方法包括:
-
Prism.parse(source)
,它将 AST 作为解析结果对象的一部分返回。 -
Prism.parse_comments(source)
,它返回注释。 -
Prism.parse_success?(source)
,如果不存在错误,则返回 true。
-
-
-
如果您有兴趣参与贡献,可以直接在 Prism 仓库 上提交 pull request 或 issue。
-
您现在可以使用
ruby --parser=prism
或RUBYOPT="--parser=prism"
来体验 Prism 编译器。请注意,此标志仅用于调试。
兼容性问题¶ ↑
-
通过以下文件打开方法创建子进程/fork 操作已被弃用。[Feature #19630]
-
URI.open
-
URI.open
-
当给定一个非 lambda、非字面块时,
Kernel#lambda
现在会抛出ArgumentError
,而不是返回未修改的值。自 Ruby 3.0.0 以来,这些用法一直在Warning[:deprecated]
类别下发出警告。[Feature #19777] -
RUBY_GC_HEAP_INIT_SLOTS
环境变量已被弃用和删除。应使用RUBY_GC_HEAP_%d_INIT_SLOTS
环境变量代替。[Feature #19785] -
在没有普通参数的块中,不带参数的
it
调用已被弃用。在 Ruby 3.4 中,it
将引用第一个块参数。[Feature #18980] -
NoMethodError
的错误消息已更改为不再使用目标对象的#inspect
以提高效率,而是显示 “instance of ClassName”。[Feature #18285]([1] * 100).nonexisting # undefined method `nonexisting' for an instance of Array (NoMethodError)
-
现在,在使用匿名参数的块中,不允许使用匿名参数转发。[Feature #19370]
Stdlib 兼容性问题¶ ↑
-
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
的单个执行。[Feature #20057] -
一些内部线程事件钩子 API 的更新
-
带有目标 Ruby 线程 (VALUE) 和回调函数 (
rb_internal_thread_event_callback
) 的rb_internal_thread_event_data_t
接收它。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()
以从特定线程获取帧。[Feature #10602] -
引入
rb_data_define()
以定义Data
。[Feature #19757] -
引入
rb_ext_resolve_symbol()
以从扩展库中搜索函数。[Feature #20005] -
IO
相关更新 -
rb_io_t
的详细信息将被隐藏,并为每个成员添加了已弃用的属性。[Feature #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 中实现新功能即可使用它们。[Feature #19637]
-
有关详细信息,请参阅 Ruby 解析器的未来愿景。
-
Lrama 内部解析器是由 Racc 生成的 LR 解析器,用于维护。
-
支持参数化规则
(?, *, +)
,它将在 Ruby parse.y 中使用。
GC
/ 内存管理¶ ↑
-
相对于 Ruby 3.2 的重大性能改进
-
旧对象引用的年轻对象不再立即提升到旧代。这显著降低了主要
GC
回收的频率。[Feature #19678] -
引入了一个新的
REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO
调整变量,用于控制导致触发主要GC
回收的未保护对象的数量。默认值设置为0.01
(1%)。这显著降低了主要GC
回收的频率。[Feature #19571] -
为许多缺少它们的内核类型实现了写屏障,特别是
Time
、Enumerator
、MatchData
、Method
、File::Stat
、BigDecimal
和其他几个。这显著减少了次要GC
回收时间和主要GC
回收频率。 -
大多数核心类现在都使用可变宽度分配,特别是
Hash
、Time
、Thread::Backtrace
、Thread::Backtrace::Location
、File::Stat
、Method
。这使得这些类的分配和释放速度更快,使用更少的内存并减少堆碎片。
-
-
使用
Object
Shapes 优化了defined?(@ivar)
。
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
被视为硬限制,在该限制下,新代码的编译停止。 -
由于代码
GC
而导致的性能突然下降。在使用 Pitchfork 进行重新 fork 的服务器上,具有更好的写时复制行为。 -
如果需要,仍然可以使用
--yjit-code-gc
启用代码GC
。 -
添加了可以在运行时启用 YJIT 的
RubyVM::YJIT.enable
-
您可以在不修改命令行参数或环境变量的情况下启动 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 个本机线程)。M:1 线程比 1: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 线程调度器的工作方式与 Ruby 1.8 的扩展版本中的 M:1 线程调度器相同。 -
M:N 线程调度器可能会为 C 扩展引入不兼容性,因此默认在主 Ractor 上禁用。
RUBY_MN_THREADS=1
环境变量将启用它。在非主 Ractor 上,M:N 线程调度器是启用的(并且现在无法禁用它)。 -
N
(本地线程的数量)可以使用RUBY_MAX_CPU
环境变量指定。默认值为 8。请注意,为了支持多种阻塞操作,会使用超过N
个本地线程。
-