Jan 01, 2025
2 min read
Rust,

Rust 开发中的编译速度与磁盘占用优化

Rust candle 模型教程

在笔者的实际开发体验中,Rust 有两个主要问题一直困扰着我:一是较慢的编译速度,二是较大的磁盘占用。本文将探讨这两个问题,并分享一些有效的解决方案。

编译速度

在使用某些第三方库时,编译速度可能会显著变慢。例如,如果你曾经使用过 async-stripe 这个 crate,你可能会注意到项目编译速度至少减慢了一倍,即使项目本身非常简单。原因在于 async-stripe 在编译时会展开生成大量的宏代码(主要来自序列化/反序列化逻辑),这使得代码库膨胀到大约 700,000 行。这种情况下,编译时间的增加是不可避免的,但我们可以通过优化依赖项和使用缓存工具来缓解这一问题。

减少依赖项和优化依赖树

依赖项的数量和复杂性对编译速度有直接影响。过多的依赖项不仅会增加编译时间,还会占用更多的磁盘空间。因此,优化依赖树是非常重要的:

  • 移除未使用的依赖:使用 cargo-udeps 工具可以帮助检测并移除未使用的依赖项。这不仅可以减少编译时间,还能减小项目的体积。安装并使用 cargo-udeps

    cargo install cargo-udeps
    cargo udeps
  • 选择更轻量级的替代方案:对于某些功能,可能存在多个 crate 提供相似的功能。选择更轻量级的 crate 可以减少依赖树的复杂性和编译产物的大小。例如,使用 smallvec 替代 Vec,或者使用 once_cell 替代 lazy_static 等。

  • 避免重复依赖:有时,多个依赖项可能引入相同的库,导致重复编译。可以通过 cargo tree 工具查看依赖树,识别并解决重复依赖的问题。运行以下命令查看依赖树:

    cargo tree

使用缓存工具

sccache 是一个分布式编译缓存工具,它可以缓存编译结果,并在后续编译时复用这些结果。sccache 甚至可以在不同机器之间共享编译缓存,这对于 CI/CD 环境特别有用。安装并配置 sccache

cargo install sccache
export RUSTC_WRAPPER=$(which sccache)

使用快速链接器 mold

mold 是一个高效的链接器,它通过优化链接过程,显著加快了链接阶段的速度。链接阶段通常是编译过程中最耗时的部分之一,特别是在处理大量依赖项时。mold 不仅减少了内存占用,还缩短了链接时间。你可以通过以下方式配置 mold 作为默认链接器:

[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/path/to/mold"]

提示:确保 mold 的路径正确,通常为 /usr/local/bin/mold 或其他安装路径。

磁盘占用

在日常开发中,target 目录的磁盘占用是一个不容忽视的问题。特别是当你的硬盘容量有限时,频繁的编译操作可能会迅速填满磁盘空间。以下是我在一个项目中清理编译缓存后的统计结果:

 cargo clean
     Removed 237,637 files, 121.0 GiB total

在我的 Macbook 上,512GB 的硬盘空间并不充裕,而我同时开发多个 Rust 项目,因此磁盘焦虑一直困扰着我。为了缓解这一问题,可以采取以下措施:

统一 target 目录

通过设置环境变量 CARGO_TARGET_DIR 或在 ~/.cargo/config.toml 中配置 build.target-dir,可以将所有项目的 target 目录统一到一个外部位置。这样做的好处是可以共享某些依赖的中间层,减少磁盘占用。缺点是构建产物不再位于项目根目录下,可能会给某些工作流带来不便。

[build]
target-dir = "~/.cache/target"

提示:确保 ~/.cache/target 目录有足够的权限,并且定期清理不再需要的编译产物。

定期清理 target 目录

除了统一 target 目录外,定期清理 target 目录也是一个有效的策略。你可以使用 cargo clean 命令手动清理,或者结合 CI/CD 流程自动化清理过程。此外,cargo-sweep 是一个专门用于清理旧依赖项的工具,可以帮助你进一步释放磁盘空间。

cargo install cargo-sweep
cargo sweep -a

使用文件系统压缩

如果你使用的是支持压缩的文件系统(如 Btrfs 或 ZFS),可以启用文件系统级别的压缩来减少 target 目录的磁盘占用。例如,在 Btrfs 上可以使用以下命令启用压缩:

sudo btrfs property set /path/to/target compression zstd

小结

Rust 的编译速度和磁盘占用问题是开发者常见的痛点,但通过合理的优化和工具使用,我们可以有效缓解这些问题。减少依赖项、使用缓存工具、优化链接器以及合理管理 target 目录,都是提升开发效率的关键手段。

当然,有钞能力的朋友,上面一切都不是问题。