SuperAPI AI 工具集

rust-profiling

编程与开发

查看项目

更新于 10-15 12:44

技能介绍

用途

Rust Profiling 是一个面向 Rust 性能剖析的技能,用于引导代理完成 Rust 程序的性能分析工作,涵盖火焰图生成、二进制体积分析、单态化膨胀测量、Criterion 微基准测试,以及解读包含内联 Rust 帧的剖析结果。

触发场景

该技能在以下问题出现时被触发:

  • 如何为 Rust 程序生成火焰图
  • Rust 二进制体积过大,如何定位原因
  • 如何编写 Criterion 基准测试
  • 如何测量单态化膨胀
  • Rust 性能低于预期时如何剖析
  • 如何在 Rust 中使用 perf

主要能力与工作流

1. 为剖析构建

使用带有调试符号的 release 配置,配置示例:

[profile.release-with-debug]
inherits = "release"
debug = true
cargo build --profile release-with-debug

或快速方式:

CARGO_PROFILE_RELEASE_DEBUG=true cargo build --release

2. 使用 cargo-flamegraph 生成火焰图

cargo install flamegraph

Linux 下使用 perf(要求 perf_event_paranoid ≤ 1):

sudo sh -c 'echo 1 > /proc/sys/kernel/perf_event_paranoid'
cargo flamegraph --bin myapp -- arg1 arg2

macOS 下使用 DTrace(需要 sudo):

sudo cargo flamegraph --bin myapp -- arg1 arg2

剖析测试与基准:

cargo flamegraph --test mytest -- test_filter
cargo flamegraph --bench mybench -- --bench

输出会在当前目录生成 flamegraph.svg,可在浏览器中打开。

自定义选项:

cargo flamegraph --freq 1000 --bin myapp

直接使用 perf 获得更多控制:

perf record -g -F 999 ./target/release-with-debug/myapp args
perf script | stackcollapse-perf.pl | flamegraph.pl > out.svg

3. 使用 cargo-bloat 进行二进制体积分析

cargo install cargo-bloat
cargo bloat --release -n 20
cargo bloat --release --crates
cargo bloat --release --filter myapp

可用于对比改动前后:

cargo bloat --release --crates > before.txt
# 进行修改
cargo bloat --release --crates > after.txt
diff before.txt after.txt

典型输出会列出文件占比、.text 占比、大小、crate 名称等。

4. 使用 cargo-llvm-lines 测量单态化膨胀

cargo install cargo-llvm-lines
cargo llvm-lines --release | head -40
cargo llvm-lines --release | grep '^myapp'

典型输出包含 Lines、Copies、Function name 三列。Copies 数量高代表单态化展开。可通过“薄泛型包装 + 具体内部函数”的方式优化:

fn process<T: AsRef<[u8]>>(data: T) -> usize {
    fn inner(data: &[u8]) -> usize { do_work(data) }
    inner(data.as_ref())
}

5. Criterion 微基准测试

依赖配置:

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }

[[bench]]
name = "my_bench"
harness = false

基准代码示例:

use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};

fn bench_process(c: &mut Criterion) {
    c.bench_function("process 1000 items", |b| {
        let data: Vec<i32> = (0..1000).collect();
        b.iter(|| process(black_box(&data)))
    });
}

fn bench_sizes(c: &mut Criterion) {
    let mut group = c.benchmark_group("process_sizes");
    for size in [100, 1000, 10000].iter() {
        let data: Vec<i32> = (0..*size).collect();
        group.bench_with_input(
            BenchmarkId::from_parameter(size),
            &data,
            |b, data| b.iter(|| process(black_box(data))),
        );
    }
    group.finish();
}

criterion_group!(benches, bench_process, bench_sizes);
criterion_main!(benches);

运行方式:

cargo bench
cargo bench --bench my_bench
cargo bench -- process_sizes
cargo bench -- --save-baseline before
cargo bench -- --baseline before
open target/criterion/report/index.html

6. 在 Linux 上使用 perf 配合 Rust

perf record -g ./target/release-with-debug/myapp args
perf record -g -F 999 ./target/release-with-debug/myapp args
perf report
perf report --stdio --no-call-graph | head -40
perf annotate myapp::hot_function
perf stat ./target/release/myapp args

Rust 相关建议:

  • 使用 debug = 1(仅行表)加快构建并保留行级归属
  • 使用 RUSTFLAGS="-C force-frame-pointers=yes" 改善调用图
  • 关闭 ASLR 以获得可复现地址:setarch $(uname -m) -R ./myapp

7. 使用 heaptrack / DHAT 分析内存分配

heaptrack(Linux):

heaptrack ./target/release/myapp args
heaptrack_print heaptrack.myapp.*.zst | head -50

DHAT(通过 Valgrind):

valgrind --tool=dhat ./target/debug/myapp args

使用 dh_view.html 打开 dhat-out.* 文件查看结果。

相关技能

  • skills/rust/rustc-basics:构建配置(调试符号、profile)
  • skills/profilers/linux-perf:perf 基础知识
  • skills/profilers/flamegraphs:读取与解读火焰图 SVG
  • skills/profilers/valgrind:使用 massif/DHAT 进行分配剖析

限制

部分操作依赖系统权限与平台工具:Linux 下 perf 需要 perf_event_paranoid ≤ 1,macOS 下 DTrace 需要 sudo。其他限制信息暂未提供。