编译时优化
问题
如何通过编译器配置提升 Rust 程序性能?
答案
Release Profile 优化
Cargo.toml
[profile.release]
opt-level = 3 # 最高优化级别
lto = "fat" # 全程序链接时优化
codegen-units = 1 # 单代码生成单元(更好的优化)
panic = "abort" # 不生成 unwind 代码
strip = true # 去除符号
target-cpu = "native" # 针对当前 CPU 优化
优化选项详解
| 选项 | 值 | 效果 | 编译时间影响 |
|---|---|---|---|
opt-level | 0/1/2/3/s/z | 优化级别 | 越高越慢 |
lto | off/thin/fat | 跨 crate 优化 | fat 很慢 |
codegen-units | 1~256 | 并行编译粒度 | 1 最慢但最优 |
panic | unwind/abort | 栈展开方式 | abort 更小更快 |
PGO(Profile-Guided Optimization)
利用运行时数据指导编译器优化:
# 1. 编译插桩版本
RUSTFLAGS="-Cprofile-generate=/tmp/pgo" cargo build --release
# 2. 运行收集数据
./target/release/my-app # 使用典型工作负载
# 3. 合并数据
llvm-profdata merge -o /tmp/pgo/merged.profdata /tmp/pgo
# 4. 使用数据重新编译
RUSTFLAGS="-Cprofile-use=/tmp/pgo/merged.profdata" cargo build --release
PGO 通常能带来 10-20% 的性能提升。
编译时间 vs 运行性能
| 目标 | 配置 |
|---|---|
| 最快编译 | opt-level = 0, lto = off, codegen-units = 256 |
| 平衡 | opt-level = 2, lto = "thin", codegen-units = 16 |
| 最佳性能 | opt-level = 3, lto = "fat", codegen-units = 1 |
常见面试问题
Q1: LTO 是什么?为什么能提升性能?
答案:
LTO(Link-Time Optimization)在链接阶段对所有 crate 做跨模块优化,包括:
- 跨 crate 内联
- 跨 crate 死代码消除
- 全程序常量传播
thin LTO 是折中方案:接近 fat LTO 的优化效果,但编译速度快很多。
Q2: target-cpu = "native" 有什么风险?
答案:
编译出的二进制只能在当前 CPU 架构上运行。如果在 AVX-512 机器上编译,放到只有 AVX2 的机器上会 crash。分发给他人的程序不要使用此选项。