【Rust日报】2023-11-21 如何将 Rust 的编译效率提高 75%

2023-11-23 13:02:03 浏览数 (1)

这是一篇来自 https://benw.is/posts/how-i-improved-my-rust-compile-times-by-seventy-five-percent 的总结和翻译,我去掉了一些不太重要的章节,保留了所有关键技术点。

Rust经常被提到的一个痛点是编译时间较慢。为了享受借用检查器、安全性和零成本抽象等好处,我们需要花费更多时间进行编译。为了测试不同的更改,我们需要建立一个基准。我电脑的配置如下:

  • AMD 5950x processor,
  • 72GB RAM
  • SATA SSD system drive.
  • 7200RPM spinning disk storage drives
  • NVME drives
  • NixOS linux distro
  • Rust 1.75 nightly

Optimization Level

这些建议来自 Bevy,它建议在开发过程中将优化级别设置得更高,以可能减少开发编译时间并提高性能。默认情况下,Rust 编译器为开发构建设置了优化级别为 0。我们将为我们的代码设置优化级别为 1,并为我们代码的所有依赖设置优化级别为 3。

代码语言:javascript复制
[profile.dev]
opt-level = 1
[profile.dev.package."*"]
opt-level = 3

这样做有一个缺点是如果错误来自依赖库,那么错误消息会少得多。因此,如果遇到棘手的错误,你可能需要调整优化级别。

Mold

Rust 编译器的基本步骤大致如下,首先读取源代码,将其转换为多种类型的 IR(中间表示),并在转换过程中执行优化。然后将该 IR 传递给由 LLVM 提供的代码生成器,该代码生成器将 IR 转换为目标文件,然后链接器将这些目标文件和其他系统库链接在一起,形成一个可执行二进制文件。关于它的更多详细信息可以在这里 找到。这是一篇非常棒的阅读材料,但对于我们在这里的讨论来说可能有些太深了。

Mold 是由Rui Ueyama开发的新链接器,旨在通过尽可能并行化加载来提高链接器性能,基准测试显示其比 Rust 的默认链接器快得多。

对于 Linux 和 Mac,默认的链接器是 ld,由 cc 运行。Windows 则使用微软的 MVC link.exe。如果你在 Linux上运行,可以直接使用 mold。如果你在 Mac上,有一个名为 Sold 的付费版本可供使用。如果 Mold 为你带来了好处,我鼓励你购买 Sold(价格非常实惠)或在他的 Github 赞助页面上赞助 Rui。遗憾的是,目前不支持 Windows 用户。Sold 对 Windows 的支持正在开发中。

在 Linux 上,实际上非常容易使用,只需安装 Mold,然后在 cargo 命令前加上 mold -run 。例如, mold -run cargo build 。也可以在 .cargo/config.toml 中启用,就像这样:

代码语言:javascript复制
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/path/to/mold"]

/path/to/mold 是模具可执行文件的绝对路径。这也是启用 Sold 的方式,只需用 Sold 路径替换模具路径,并将目标更改为 Mac 的编译目标。

Cranelift

在上面的优化中,我们替换了 Rust 编译器使用的链接器。现在让我们尝试替换代码生成器,Cranelift 是一种替代代码生成器,在构建步骤中代替了 LLVM。虽然它不擅长进行像 LLVM 那样的许多优化,但它擅长快速生成代码。最近,它作为 Rust 1.73 夜间版的 x86_64 linux 目标代码生成进行了集成。其他平台需要单独设置 cranelift,请参阅它的 README。

代码语言:javascript复制
rustup update nightly #install nightly if you haven't already
rustup component add rustc-codegen-cranelift-preview --toolchain nightly

要在 Cargo 中使用它,可以通过启用不稳定的 codegen-backend 功能,并为配置文件设置 codegen-backend= "cranelift" 值来启用它。可以在 .cargo/config.toml 中这样做:

代码语言:javascript复制
[unstable]
codegen-backend = true
[profile.server-dev]
codegen-backend = "cranelift"

当然,你也可以只对某个目标启用:

代码语言:javascript复制
[target.x86_64-unknown-linux-gnu]
rustflags = ["-Zcodegen-backend=cranelift"]

需要注意的是,Cranelift 仍在开发中,可能存在一些缺少内在功能的问题。因此,部分 crate 可能无法在正常地工作。如果您发现缺少什么功能,我鼓励您提交 Issue,可能会有可用的解决方法。

Conclusion

经过一系列的测试和评判(可以看原文),我们发现启用 MoldCranelift 为我带来了 75% 的增量编译时间缩短和 25% 的冷编译时间缩短,这是相当大的改进。使用 Cranelift 需要 Nightly 版本的 Rust,这可能会让一些项目感到不理想,而且 Mold 需要 Linux,而 Sold 需要 Mac(并且需要付费),对我来说,这进一步证明了Rust Web 开发应该在某种 Linux 或 Mac 上进行,而不是在 Windows 上。WSL2 可能有助于改善情况,但可能会更慢。由于我有一台 Mac 笔记本和一台 Linux 工作站,我将为我的 Mac 购买 Sold,并在可以的项目中使用Cranelift。


From 日报小组 Koalr

社区学习交流平台订阅:

  • Rustcc论坛: 支持rss
  • 微信公众号:Rust语言中文社区

0 人点赞