最近有网友在Rust众的tg群吐槽rust随便改几行都要编译十几秒,网友图波列夫图160重型超音速可变后掠翼战略轰炸猫猫! 给出的建议是把默认的gcc的ld换成llvm的lld
我试了下像修改源码几行这种只需增量编译一个crate,但需要重新linking相关object的场景,确实90%的时间都花在linking上
我试着把ld换成lld之后结果增量编译从十几秒加快到几秒,感谢网友的分享!
- Rust最佳实战篇 - slides
- The Rust Performance Book
- bevy book
- https://github.com/bevyengine/bevy/blob/main/.cargo/config_fast_builds
mac不支持lld可以用类似的zld
linux可以直接装lld也可以rustup component add llvm-tools-preview
+cargo binutlis
获取rust-lld
可执行文件再写个软链接把rust-lld改名成lld
# https://github.com/bevyengine/bevy/blob/main/.cargo/config_fast_builds
[target.x86_64-unknown-linux-gnu]
linker = "/usr/bin/clang"
rustflags = ["-C", "link-arg=-fuse-ld=lld", "-Zshare-generics=y"]
[build]
rustc-wrapper = "/home/w/.cargo/bin/sccache"
[profile.dev]
split-debuginfo = "unpacked"
[profile.test]
split-debuginfo = "unpacked"
我们知道增量编译时可能只有一个crate的改动,所以80%-90%的时间都在link executable很正常,慢的是linking的时间
试了个370个crate的项目,单元测试内仅一行let a=1;
,修改a的值要增量编译一个crate,link两个object
不用lld耗时16秒,用lld耗时8秒,频繁修改单元测试用例或增量编译时,lld的编译速度能快一倍
测试机器honorbook pro amd 4600H款,rustc nightly-2021-04-24,async-graphql 源码 2.8.4
所谓全新编译就是 cargo clean 后 cargo build,下面对比编译时间
- 使用默认的gcc ld: 1m 00s
- 1的基础上ld换成lld优化: 40.32s
- 2的基础上加上
linker="/usr/bin/clang"
优化: 40.24s - 3的基础上加上
-Zshare-generics=y
优化: 41.62s - 4的基础上加上
split-debuginfo="unpacked"
优化: 42.42s - 5的基础上加上
sccache
优化: 41.33s
小结: 也就ld换成lld能有巨大的编译速度提升,增量编译1个crate时甚至能有100%的提升,其它优化选项几乎没有任何性能提升
又测试了一个230个crate左右的服务器项目,用去掉除lld以外的优化配置文件,结果编译耗时从45s增加到58秒
所以看上去linker="/usr/bin/clang"
和sccache
几乎没用
所以完全没必要加上sccache的编译期缓存工具
# https://bevyengine.org/learn/book/getting-started/setup/#enable-fast-compiles-optional
[target.x86_64-unknown-linux-gnu]
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y", "-Ctarget-cpu=znver3"]
# rustup component add llvm-tools-preview && cargo install binutils
[target.x86_64-pc-windows-msvc]
linker = "rust-lld.exe"
rustflags = ["-Zshare-generics=y"]
[profile.dev]
split-debuginfo = "unpacked"
[profile.test]
split-debuginfo = "unpacked"
虽然lld兼容gcc后端,但我们生产环境依然用GNU的ld