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/readlineAPI 兼容的纯 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。这使得这些类的分配和释放速度更快,使用更少的内存并减少堆碎片。
-
-
使用
ObjectShapes 优化了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个本地线程。
-