Crystal(Crystal) 1.22.0 发布,亮点包括标准流模拟 SIGPIPE、重构 DWARF 解析提升性能、所有目标支持原生事件循环、支持 LLVM(LLVM) 23 和 24,以及 aarch64-linux 晋升为 Tier 1。我们发布 Crystal 1.22.0,带来若干新特性和错误修复。预编译包已在 GitHub Releases(GitHub Releases)和官方分发渠道提供,安装说明见 crystal-lang.org/install。自 1.21.1 以来,本次发布包含 33 位贡献者提交的 251 项变更,感谢所有贡献者为改进这门语言付出的努力。下面列出语言、编译器和标准库中最值得注意的变化。
正文
亮点
- 标准流模拟 SIGPIPEstdlib/runtime
- 为性能重构 DWARF 解析stdlib/runtime
- 所有目标平台支持原生事件循环stdlib/runtime
- 支持 LLVM 23 和 24stdlib/llvm
aarch64-linux升级为 Tier 1platform/linux
Crystal 1.22.0 现已发布,包含多项新特性和错误修复。
预编译包可在 GitHub Releases 和官方分发渠道获取。安装说明见 crystal-lang.org/install。
此版本包含自 1.21.1 以来的 251 项变更,由 33 位贡献者完成。
下面列出语言、编译器和标准库中最值得注意的变更。更多细节见完整更新日志。
当向 STDOUT 或 STDERR 写入因 EPIPE 失败时,Crystal 进程会立即退出。这与 SIGPIPE 信号的默认行为非常相似。此前,失败的写入会抛出 IO::Error,通常会打印错误信息并退出。现在这一错误信息已被移除(#17335)。
你可以通过 STDOUT.exit_on_broken_pipe = false 来关闭这一行为。
常量现在可以带类型声明(#16951)。其行为与常量和类型声明结合时应有的表现完全一致。
module Foo
BAR : Int32 = 1
BAZ : String = ""
QUX : Int64 = 123 # autocasts 123 to Int64
end
aarch64-linux-gnu 和 aarch64-linux-musl 目标从 Tier 2 升至 Tier 1。此前唯一欠缺的是官方构建,但自 1.19 起已经提供。
Process.fork 在 1.0 之前就已废弃,现在终于将其移除(#17367)。
- 新的宏支持更多编译时文本操作:
StringLiteral#bytesize(#17176)、NumberLiteral#chr(#17169),以及RangeLiteral#each支持CharLiteral(#17170)
新增常量 Crystal::ALL_FLAGS 和 Crystal::USER_FLAGS,用于访问编译时标志(#17392)。
我们彻底重构了 DWARF 解析,以提升性能并减少内存占用。DWARF 解析器现在按需扫描各段(#17283),并只构建一次高效索引表(#17410、#17455),从而实现极快的查找。已解码的回溯行会缓存在 LRU 缓存中(#17285)。
还增加了对 DWARF 5 特性 DW_FORM_addrx<n> 和 DW_FORM_strx<n> 的支持(#17445)。
我们合并了大量针对 HTTP 的改进和错误修复。
#remote_address和#local_address从HTTP::Request移到HTTP::Context(#17196)- 新增
HTTP::Headers#merge(#17326) - 在 HTTP body 中序列化
IO::Memory并带上Content-Length头(#17388)
错误修复:
- 拒绝无法识别的 HTTP
Transfer-Encoding头(#17140)、无效的Content-Encoding(#17262)以及无效的 HTTP trailer(#17337) - [破坏性] 修复
HTTP::Request#body=和#content_length=的返回值(#17257、#17273) - 修复
HTTP.parse_headers_and_body,使其在without_zlib下不再抛出异常(#17272) - 校验
HTTP::WebSocketHandler(#17235)、HTTP::Request(#17255、#17304、#17374、#17310、#17312、#17258)以及HTTP::Headers名称(#17317)的属性 - 在请求期间遇到
IO::Error时关闭HTTP::Client(#17318) - 修复
Content-Encoding: deflate(#17261) - 修复
HTTP::Request.from_io解析空头名称的问题(#17254) - 修复
HTTP::Request#form_params?,使其忽略无效的 content-type(#17256)
所有目标平台都支持直接基于系统选择器的原生事件循环,并默认使用它。
我们在 Solaris 上启用了 epoll(#17370),并在其余所有 BSD 目标上启用了 kqueue(#17421、#17420)。libevent 仍可作为后备方案,但现在必须显式选择启用,且在技术上已逐渐过时。我们预计会在后续版本中废弃它。
我们终于在 OpenSSL 绑定中默认启用了对 Kernel TLS 的支持(#17059)。
注意
此功能已在 1.22.1 中被回退,并将保持禁用。
File.exists?(#17307),以及File::Info.readable?、.writable?、.executable?现在接受follow_symlinks: false参数(#17391)- 新增
Char::Reader.new(Bytes)(#17428) - 新增
Time::Span#to_nanoseconds等方法(#17190) - 新增
GC.syscall(&)(#17150) 修复在 musl-libc 上使用
-static-pie链接时的回溯问题(#17316)大写实例变量和类变量(#17160)
HTTP::Request#local_address和#remote_address(#17260)LLVM::Type#size和#alignment(#17494)支持 LLVM 23.1 和 24.0(#17432)
- 更新 markd 至 0.6.0(#17269)
更新 distribution-scripts(#17178)带来了包依赖、Docker 基础镜像等的升级。
这是首个提供 aarch64-windows-msvc 构建的版本。
Crystal 在 RFC 30 中确立了前向兼容策略:构建 Crystal 1.22 需要 1.14 或更高版本的 stage-0 编译器。
评论
讨论气氛呈现两极:一边质疑 Crystal 的现实意义、采用率和明确用例,认为它只是「没有护城河的快速 Ruby」;另一边的实际使用者则强调,它在 CLI、小型服务和从 Ruby 移植时能带来显著性能与内存收益,并对 aarch64 与 Windows 支持进展表示欢迎。分歧主轴在于:它究竟是一门被埋没的高效 Ruby 式语言,还是一个错过时机、生态与运行时都不够成熟的陪跑者。
质疑 Crystal 的现实意义、采用率与关键工具,认为不值得投入
- 认为它不与 Ruby 互通,也看不到知名公司使用;官网缺少清晰的使用场景与使命定位,移除 REPL 更让早期关注者转投 Elixir。有人直接称它是「没有护城河的快速 Ruby」并不再考虑。(较多人) > 它既不与 Ruby 互通,也没有知名公司使用,我不确定为什么要学这门语言。(@pelcg)
肯定 Crystal 在 CLI、小型服务与 Ruby 迁移中的实际价值
- 实际用于小型服务器部署很方便;把 Ruby 代码移植到 Crystal 后,几乎不用改代码就能获得约 40 倍性能提升和 3 倍内存下降。也有实践者认为它是很好的 CLI 语言,团队至今仍在推进。(较多人) > 我把之前的 Ruby 代码移植过来,几乎保持原样就拿到了约 40 倍性能提升和 3 倍内存下降。(@viraptor)
认为 Crystal 的语言设计有亮点,但成熟度和时机不足
- 欣赏它基于 LLVM、拥有极轻量绿色线程、C 互操作和编译期宏系统,能在保留 Ruby 式面向对象语法的同时提供原生性能;但认为它仍需打磨、缺乏资金,且 Windows 支持来得晚,可能在另一个时间线才能起飞。(少数人) > 它基于 LLVM,有极其轻量的绿色线程、C 互操作和编译期宏系统,让我这个不用 Ruby 的人也觉得很惊艳。(@giancarlostoro)
欢迎 aarch64 与 Windows 支持,认为跨平台成熟有助采用
- aarch64-linux 升到 Tier 1 让移植服务到廉价 Hetzner 机器更有说服力;Windows 支持持续进展也受肯定。有人强调编程语言应尽快覆盖三大平台,而 Crystal 的 Windows 支持直到 2023 年才开始,被认为太晚。(少数人) > aarch64-linux 终于升到 Tier 1,我可以说服 CTO 把一些服务移植到 Crystal,跑在那些便宜的 Hetzner 机器上了。(@opem)
指出长时运行程序的运行时稳定性问题,部分用户因此转向 Go
- 在长时运行程序中,I/O 期间的某些异常会让运行时停止,因此虽然适合 CLI,却不得不放弃;另有用户用了一年后因为 Go 构建更快而转去 Go,并提到 Bun 在降低内存占用上进步很快,对预算服务器有吸引力。(少数人) > 我们在长时运行程序里不得不放弃 Crystal,因为 I/O 期间某些异常会把整个运行时卡死。(@rubiquity)
有价值的补充
- 定位类比:Crystal 被形容为「带类型的 Ruby」,同时具备 Go 的性能与并发流。(@sumnole)
- 冷知识:Crystal 最初用 Ruby 写成,后来才转为自举;Windows 支持直到 2023 年才开始。(@giancarlostoro)
- 技术特性:它基于 LLVM,绿色线程极轻量,具备 C 互操作,以及可在编译期检查 AST、生成代码并消除样板代码的宏系统。(@giancarlostoro)