Hacker News 中文摘要

RSS订阅

Crystal 1.22 正式发布 -- Crystal 1.22

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 项变更,感谢所有贡献者为改进这门语言付出的努力。下面列出语言、编译器和标准库中最值得注意的变化。

正文

亮点

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)