Hacker News 中文摘要

RSS订阅

2026年9月如何加速 Rust 编译器 -- How to speed up the Rust compiler in September 2026

两个月前关于 Rust 编译器(Rust compiler)性能的文章发表后,许多事发生。2026-07-29 至 2026-09-28 的测量显示,平均墙钟时间降低 4.57%,629 项基准中 555 项改善、74 项回退。诺亚·列夫(Noah Lev)此前在 Rust 文档工具(rustdoc)上获巨大加速,近期撰文详述;雅库布·贝拉内克(Jakub Beránek)在 PR 159642 中为代码检查工具(Clippy)启用 PGO 改善耗时。

正文

我关于 Rust 编译器性能的上篇文章是两个月前发的,从那以后发生了很多事。

总体进展

2026-07-29 到 2026-09-28 期间的测量结果显示,平均墙钟时间减少了 4.57%,在短短两个月里堪称惊人。在 629 项基准测量中,555 项有所提升,只有 74 项退步。不少基准实现了两位数百分比的降低。用专业术语说,这结果就是“一片绿海”(a sea of green)。

rustdoc

在上篇文章里我提到 Noah Lev 在 rustdoc 上取得了巨大的速度提升。他最近写了一篇帖子详细解释具体做法,读起来很有趣也令人满足。

Clippy

在 #159642 这个 PR 中,Jakub Beránek 为 Clippy 启用了 PGO(配置文件引导优化),使得大多数 Clippy 基准的墙钟时间得到改善,最佳情况提升了 18%。

LLVM 更新

在 #158734 这个 PR 中,Nikita Popov 将编译器使用的 LLVM 版本升级到了 LLVM 23。正如我们升级 LLVM 时常发生的那样,看到了一些不错的加速。所有基准的平均墙钟时间减少了 1.2%,听起来不多,但对单个 PR 来说非常了不起。

新借用检查器

新的借用检查器 Polonius Alpha(与电影《Napoleon Dynamite》无关)已在 Nightly 上启用。它比现有借用检查器更精确,能接受一些旧检查器会拒绝的有效程序。但它确实做了更多工作,足以在少数情况下(包括流行的 serde crate)对编译时间产生可测量的影响。幸好 Jack Huey 在处理此事。

在 #161938 中,Jack 让一些活跃性(liveness)计算变为惰性,将 serde 的指令数减少了 3-5%,其他一些基准减少不到 1%。

在 #163027 中,Jack 调整了一个数据结构并微调了内联,在众多基准上实现了基本低于 1% 的指令数减少。

要消除剩余的 Polonius Alpha 性能退化还需更多工作,但“一片绿海”的结果表明,这些退化已被近期许多其他改进所掩盖。

新 trait 求解器

新的 trait 求解器 Penelope Hammertime(编辑注:是这样吗?)也在 Nightly 上启用了。正如我所说,很多事情正在发生。

和新的借用检查器类似,新 trait 求解器在少数情况下更慢。Jana Dönszelmann 写了一篇详细帖子介绍改进这个新求解器性能的努力。

Jana 的帖子足够详细,我就不多谈新求解器大量的进行中工作了,只顺带提一下我做的几个 PR:#160479、#160605、#160801、#160892、#161077 和 #161211。其中一些让某些极端 crate 的编译时间大幅减少:这里降 50%,那里降 25%,那里降 15%,在一个压力测试上甚至更多。而且不止我一人取得了进展……去读 Jana 的帖子吧。

xmakro

新贡献者 xmakro 延续了良好的改进势头。

在 #157281 中,xmakro 优化了构建特化图(specialization graph)时的 impl 处理,让所有基准的平均周期计数减少了 1.58%,对单个 PR 来说是个巨大的数字。

在 #158059 中,xmakro 优化了增量编译数据加载的一个方面,降低了多个基准的指令数,最佳情况降了 6%。

在 #160473 中,xmakro 在一条热门的 obligations 处理路径中避免了部分分配,降低了众多基准的指令数,最佳情况降了 2%。

在 #160268 中,xmakro 将新旧 trait 求解器选择代码从动态分发改为静态分发,从而避免大量分配,在不少基准上实现了基本低于 1% 的指令数减少。这个热门分配路径在性能剖析中出现了好一阵子,我早先在 #155714 试过完全相同的想法,但因为几个基准出现退化(可能由于 #[inline] 属性放置位置略有不同)而作罢。看到这个明显的低效被修复真好。

数据流分析

在 #160193 中,我更改了编译器中数据流分析使用的 CFG 遍历算法。这些分析会迭代至不动点,遍历算法会影响达到不动点的速度。对大多数代码新算法没区别,但 cranelift-codegen crate 有一个超过 18000 个基本块的巨型函数。旧算法对该函数里借用检查器所用的 EverInitializedPlaces 分析需要调用 150 万次 apply_effects_in_block 才能达到不动点;新算法只需 9 万次。这让该 crate 的 check 构建墙钟时间大幅减少了约 30%。

在 #160033 中,我再次提升了 EverInitializedPlaces 的效率,这次是通过不追踪投影上不必要的数据。这让 match-stress 基准的指令数减少了 17%,少数其他基准减少不到 1%。

LLM

LLM 在某些分析上已经变得非常擅长。我仍然自己写所有代码和文字,因为(a)这至关重要,(b)项目政策要求如此,但提到的几个 PR 中我得到了有用的 LLM 分析协助。

总之说得够多了。

杂项

在 #160535 中,Chris Denton 增大了编译器的默认栈大小,从而得以移除手动栈扩展机制 ensure_sufficient_stack。这个改动引发了很多讨论,因为很难决定如何处理栈耗尽。但性能影响是明确的,众多基准指令数减少,最佳情况几乎降了 3%。

在 #160506 中,项目使用了大量“rollup” PR(多个 PR 合并在一起),因为我们没有足够 CI 容量逐个合并。通常影响性能的 PR 会单独合并以便清晰测量。但有史以来第一次,排队等待的性能改进 PR 太多,Jonathan Brouwer 创建了一个包含 10 个性能改进 PR 的 rollup 来推进流程!这是个好问题。后来还有 #162859 包含了四个性能改进 PR。(不用担心意外影响,因为我们有能力在合并后对这些 PR 单独跑性能基准套件,确保各自达到预期效果。)

在 #162747 中,我对将 AST 降级为 HIR 的代码做了些小改进。本是个不该影响性能的清理,却降低了众多基准指令数,最佳情况降了 1.5%。有时就是这么走运。

工作状态

明天我将入职 Hexcat,参与编译器性能优化项目目标。令人兴奋!

编辑后记

新求解器的名字不是 Penelope Hammertime,那是个玩笑。它的真名是 Pineapple Häagen-Dazs。

评论

社区普遍赞赏 Rust 编译器近期通过算法重构实现的明显加速。但部分用户仍因编译速度落后于 Go 等语言而转向其他语言,并对大厂支持力度有更高期待。

认为最大加速源于算法改变而非优化热循环

  • 通过改变控制流图遍历方式使某关键调用从百万级降至九万级,新求解器做到按需做昂贵分析,两个月平均墙钟降约 4.57% 被视为卓越进展(较多人)。 > 最大的编译器优化常来自改算法,而不是死磕热循环(@Citrusoff)

认为改进借用检查器的同时还能提速难能可贵

  • 在让借用检查器能验证以往会报错代码的前提下仍取得 5% 加速,打破了正确性提升必牺牲性能的预期(较多人)。 > 有时我们真能既保住蛋糕又把它吃了(@bryanlarsen)

认为企业捐赠已带来可衡量回报并期待更多

  • 大公司资助开源维护者直接转化为编译体验改善,告知企业员工节省 5% 等待时间可促未来投资;有人戏谑希望 AI 团队捐海量算力(较多人)。 > 让企业知道员工少等 5% 编译时能激励它们投资维护者(@adamch)

认为编译慢仍是阻碍采用的核心痛点

  • 在智能体编程时代快速迭代是刚需,Rust 编译耗时远超 Go,导致不少人将多数业务迁至 Go,仅留少数场景用 Rust(少数人)。 > 智能体时代快速迭代优势巨大,而 Rust 编译比 Go 慢太多(@slowin)

通过拆 crate 与增量编译在实践中获益

  • 将单一大 crate 拆分成三个可真正利用并行;增量编译持续拿下易得的胜利,但剩余耗时是否仍在旧瓶颈存疑(较多人)。 > 把一个胖 crate 拆成三个后并行度就真起来了(@hnp9j9qtda)

有价值的补充

  • 新 Polonius 及特征求解器正将编译器性能问题转向“仅在真正需要时做昂贵分析”这一更有趣的命题。
  • 有外部开发者好奇 Rust 编译器为何慢、性能杀手何在以及与 C 编译器的比较,讨论中未深入解答,反映圈外对编译耗时的普遍疑惑。