NEWS for Ruby 3.3.0¶ ↑
本文档列出了自 3.2.0 版本以来用户可见的功能更改,不包括错误修复。
请注意,每个条目都保持在最低限度,详细信息请参阅链接。
命令行选项¶ ↑
-
引入了新的
performance
警告类别。即使在详细模式下,它们默认也不会显示。使用-W:performance
或Warning[:performance] = true
启用它们。 [Feature #19538] -
引入了一个新的
RUBY_CRASH_REPORT
环境变量,允许将 Ruby 崩溃报告重定向到文件或子命令。 有关更多详细信息,请参阅 ruby 手册页的BUG REPORT ENVIRONMENT
部分。 [Feature #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
端点处理无始范围。 [Feature #18515] -
Range#reverse_each
现在会为无限范围引发TypeError
。 [Feature #18551] -
添加了
Range#overlap?
,用于检查两个范围是否重叠。 [Feature #19839]
-
-
-
添加
Refinement#target
作为 Refinement#refined_class 的替代方法。 Refinement#refined_class 已被弃用,将在 Ruby 3.4 中删除。 [Feature #19714]
-
-
-
基于缓存的优化现在支持环视和原子分组。 也就是说,包含这些扩展的
Regexp
的匹配现在也可以在输入字符串长度的线性时间内执行。 但是,这些不能包含捕获,也不能嵌套。 [Feature #19725]
-
-
-
String#unpack
现在会为未知的指令引发ArgumentError
。 [Bug #19150] -
String#bytesplice
现在接受要复制的源字符串的新参数 index/length 或范围。 [Feature #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
。 [Feature #19572]
-
标准库更新¶ ↑
-
如果用户
require
以下 gem 而没有将它们添加到 Gemfile 或 gemspec,RubyGems 和Bundler
会发出警告。 这是因为它们将在未来版本的 Ruby 中成为捆绑的 gem。 如果您使用 bootsnap gem,则此警告将被抑制。 我们建议至少运行一次带有DISABLE_BOOTSNAP=1
环境变量的应用程序。 这是此版本的限制。 [Feature #19351] [Feature #19776] [Feature #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
-
debug 1.9.1
有关默认 gem 或捆绑 gem 的详细信息,请参阅 GitHub 版本,例如Logger或更改日志。
Prism
¶ ↑
-
引入Prism 解析器作为默认 gem
-
Prism
是 Ruby 语言的可移植、容错和可维护的递归下降解析器
-
-
Prism
已准备好用于生产环境并积极维护,您可以将其用于替代Ripper
-
Prism
既是一个 C 库(将由 CRuby 内部使用),又是一个 Ruby gem,可供任何需要解析 Ruby 代码的工具使用 -
Prism
API 中的主要方法是-
Prism.parse(source)
,它返回作为解析结果对象一部分的 AST -
Prism.parse_success?(source)
,如果没有任何错误,则返回 true
-
-
如果您有兴趣贡献,可以直接在Prism 存储库上提出拉取请求或问题
-
您现在可以使用
ruby --parser=prism
或RUBYOPT="--parser=prism"
来试验Prism
编译器。 请注意,此标志仅用于调试。
兼容性问题¶ ↑
-
通过以下文件打开方法创建/fork 子进程已弃用。 [特性 #19630]
-
当给定非 lambda、非文字块时,
Kernel#lambda
现在会引发ArgumentError
,而不是原样返回。 自 Ruby 3.0.0 以来,这些用法一直在Warning[:deprecated]
类别下发出警告。[特性 #19777] -
RUBY_GC_HEAP_INIT_SLOTS
环境变量已弃用并已删除。 应改为使用环境变量RUBY_GC_HEAP_%d_INIT_SLOTS
。[特性 #19785] -
在没有普通参数的块中调用不带参数的
it
已弃用。it
将在 Ruby 3.4 中引用第一个块参数。[特性 #18980] -
NoMethodError
的错误消息已更改为不使用目标对象的 inspect 以提高效率,而是显示“ClassName 的实例”。 [特性 #18285]([1] * 100).nonexisting # undefined method `nonexisting' for an instance of Array (NoMethodError)
-
现在,在使用匿名参数的块内不允许使用匿名参数转发。[特性 #19370]
Stdlib 兼容性问题¶ ↑
-
racc
被提升为捆绑 gem。-
如果您在 bundler 环境下使用
racc
,则需要在Gemfile
中添加racc
。
-
-
ext/readline
已停用-
我们有与
ext/readline
API 兼容的纯 Ruby 实现的reline
。 我们将来将依赖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 的更新
-
具有目标 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()
以从特定线程获取帧。[特性 #10602] -
引入
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
。 这使得这些类的分配和释放速度更快,使用更少的内存并减少了堆碎片。
-
使用
Object
形状优化了defined?(@ivar)
。
YJIT¶ ↑
-
与 Ruby 3.2 相比,性能有重大改进
-
改进了对 splat 和 rest 参数的支持。
-
为虚拟机的堆栈操作分配了寄存器。
-
编译了更多带有可选参数的调用。
Exception
处理程序也已编译。 -
不支持的调用类型和巨型调用站点不再退出到解释器。
-
内联了 Rails 的基本方法,例如 blank? 和 {specialized 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 个原生线程)。 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 线程调度器的工作方式类似于 M:1 线程调度器,并在 Ruby 1.8 的基础上进行了进一步扩展。 -
M:N 线程调度器可能会为 C 扩展引入不兼容性,因此默认情况下在主 Ractor 上禁用。
RUBY_MN_THREADS=1
环境变量将启用它。在非主 Ractor 上,M:N 线程调度器已启用(现在无法禁用)。 -
可以使用
RUBY_MAX_CPU
环境变量指定N
(原生线程的数量)。 默认值为 8。 请注意,为了支持多种阻塞操作,将使用超过N
个原生线程。
-