Zig 构建正变得越来越快
原文由 Mitchell Hashimoto 于 发布,订阅该博客
Andrew Kelley 有句名言(或者说恶名昭彰的话,取决于你的立场):“编译器实在太慢了,这就是我们有 bug 的原因。”1
因此,多年来,更快的编译速度一直是 Zig 最主要的公开目标之一。为了实现这一目标,Zig 团队一直在攻克极其困难的技术难题(比如抛弃 LLVM、编写自己的代码生成后端、打造自己的链接器,以及全面推进增量编译)。2
这项历时多年的努力终于在 Zig 0.15.1 中开始显现成果。Ghostty 项目刚刚完成了向 Zig 0.15.1 的升级,我想分享一些真实环境下的构建耗时。3
构建脚本编译
- Zig 0.14:7秒167毫秒
- Zig 0.15:1秒702毫秒
这是构建 build.zig 脚本本身所需的时间。上述时间是通过运行 zig build --help 测得的。
一个编写良好的构建脚本应该很少需要重新构建自身。然而,对于每一次全新的无缓存源码构建(例如用户下载项目后首次从源码构建),都需要付出这一成本。因此,它直接影响到构建出可用二进制文件所需的时间。
完整无缓存的 Ghostty 二进制构建
- Zig 0.14:41秒
- Zig 0.15:32秒
这其中包含了构建脚本本身的时间。结合前面的结果,Zig 0.15 在构建其余部分时快了约 2 秒。不过,从总耗时上依然可以看出这次初始构建时间的提升。
重要提示:其中大部分构建仍在使用 LLVM。 Ghostty 暂时还无法完全使用自托管的 x86_64 后端来构建和链接,因为该后端仍存在一些 bug。因此,这仅仅体现了 Zig 编译器本身的整体改进,即使在仍使用 LLVM 的情况下也是如此。
一旦 Ghostty 能够完全使用自托管的 x86_64 后端,我预计这一时间将骤降至 25 秒左右甚至更短,仅为使用 Zig 0.14 时所需时间的一半。
增量构建(Ghostty 可执行文件)
- Zig 0.14:19秒
- Zig 0.15:16秒
这是在对最核心的终端模拟代码做了一行修改后(在转义序列解析器中添加了一次日志函数调用)重新构建 Ghostty 所需的时间。
这次构建的构建脚本和依赖图已完全缓存,因此只会重新构建必要的部分。Zig 的增量编译目前尚未可用,所以仍会重新编译相当多的代码。此外,和上一节一样,这次构建仍在使用 LLVM。仅是去掉 LLVM,我预计这一时间就能降至约 12 秒左右(省去了 LLVM 生成代码的时间)。
更进一步,一旦 Zig 支持增量编译,我预计这类增量构建最慢也能在毫秒级内完成。不过,还是等到真正实现时再看吧。
增量构建(libghostty-vt)
- Zig 0.14:2秒884毫秒
- Zig 0.15:975毫秒
这是仅对 libghostty-vt 做了一行修改后重新构建所需的时间。与 Ghostty 可执行文件不同,libghostty-vt 已完全可以在自托管的 x86_64 后端上正常工作,因此这体现了在没有 LLVM 参与的情况下构建时间的差异。
和 Ghostty 可执行文件类似,由于增量编译尚未完全可用,这次仍会重新构建 libghostty-vt 的整个 Zig 模块。我预计一旦增量编译成为现实,这一时间最慢也会降至个位数毫秒。
但即便如此,一个并不简单的库能在不到一秒内完成构建,已经非常惊人了。这正是我目前投入最多时间开发的库,自从升级到 Zig 0.15.1 后的短短几天里,我就已经感受到了工作流上的巨大不同。以前在构建或测试的间隙,我可能会切出去看封邮件,而现在构建如此之快,我完全可以保持在终端中的专注状态,不被打断。
这一改进最能预示短期内的发展趋势。 自托管的 x86_64 后端已经足够稳定,默认可以构建所有 debug 构建,而 aarch64 后端也在接近这一水平。虽然我们暂时还无法构建完整的 Ghostty 可执行文件,但我相信这个问题会在几个月内得到解决。
更快的构建已经到来
如你所见,使用 Zig 0.15.1 构建 Ghostty 在每一种场景下都更快,尽管 Ghostty 的很大一部分仍无法利用自托管后端!而且增量编译甚至还没有可用!
我很庆幸当初为 Ghostty 选择了 Zig,也很高兴他们如此专注于编译速度。这些提升是实实在在的,而且就在当下。并且我猜想,在未来一两年里,今天公布的这些成绩看起来都会显得相当慢了。😜
脚注
带时间戳的链接:https://youtu.be/5eL_LcxwwHg?t=565 ↩
这里忽略了为让 Zig 编译器的方方面面变得更快、更可并行化等所付出的海量工作。↩
所有测试均在同一台 x86_64 Linux 机器上完成。↩
随机一篇博客
评论
登录后参与讨论