rust-profiling について
rust-profilingは、Rustの性能やバイナリサイズを調べるエージェント向けスキルです。フレームグラフ、perf、アロケーション分析、Criterionベンチマークの手順を扱います。
主な機能
- 01cargo-flamegraphによるフレームグラフ
- 02cargo-bloatによるバイナリサイズ分析
- 03cargo-llvm-linesによる単相化分析
- 04Criterionマイクロベンチマーク
- 05perfとアロケーションの分析
活用シーン
- 01Rustプログラムのホットパス特定
- 02予想外に大きいバイナリの調査
- 03単相化による膨張の測定
- 04Criterionベンチマークの作成と実行
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill rust-profilingインストール後、Claude Code で/rust-profilingを入力して読み込まれたか確認します。
同梱ファイルreferences/cargo-flamegraph-setup.md
詳細
Rust のプロファイリング
目的
cargo-flamegraph によるフレームグラフ、バイナリサイズの分析、モノモーフィゼーションによる肥大化の測定、Criterion のマイクロベンチマーク、インライン化された Rust フレームを含むプロファイリング結果の解釈を通じて、エージェントが Rust のパフォーマンスをプロファイリングできるように案内します。
トリガー
- 「Rust プログラムのフレームグラフを生成するにはどうすればよいですか?」
- 「Rust のバイナリが大きすぎます。原因を調べるにはどうすればよいですか?」
- 「Criterion のベンチマークはどのように書けばよいですか?」
- 「モノモーフィゼーションによる肥大化を測定するにはどうすればよいですか?」
- 「Rust のパフォーマンスが予想より悪いです。プロファイリングするにはどうすればよいですか?」
- 「Rust で perf を使用するにはどうすればよいですか?」
ワークフロー
1. プロファイリング用にビルドする
# Release with debug symbols (needed for readable profiles)
# Cargo.toml:
[profile.release-with-debug]
inherits = "release"
debug = true
cargo build --profile release-with-debug
# Or quick: release + debug info inline
CARGO_PROFILE_RELEASE_DEBUG=true cargo build --release
2. cargo-flamegraph によるフレームグラフ
# Install
cargo install flamegraph
# Linux: uses perf (requires perf_event_paranoid ≤ 1)
sudo sh -c 'echo 1 > /proc/sys/kernel/perf_event_paranoid'
cargo flamegraph --bin myapp -- arg1 arg2
# macOS: uses DTrace (requires sudo)
sudo cargo flamegraph --bin myapp -- arg1 arg2
# Profile tests
cargo flamegraph --test mytest -- test_filter
# Profile benchmarks
cargo flamegraph --bench mybench -- --bench
# Output
# Generates flamegraph.svg in current directory
# Open in browser: firefox flamegraph.svg
フレームグラフのカスタムオプション:
# More samples
cargo flamegraph --freq 1000 --bin myapp
# Filter to specific threads
cargo flamegraph --bin myapp -- args 2>/dev/null
# Using perf directly for more control
perf record -g -F 999 ./target/release-with-debug/myapp args
perf script | stackcollapse-perf.pl | flamegraph.pl > out.svg
3. cargo-bloat によるバイナリサイズの分析
# Install
cargo install cargo-bloat
# Show top functions by size
cargo bloat --release -n 20
# Show per-crate size breakdown
cargo bloat --release --crates
# Include only specific crate
cargo bloat --release --filter myapp
# Compare before/after a change
cargo bloat --release --crates > before.txt
# make changes
cargo bloat --release --crates > after.txt
diff before.txt after.txt
一般的な出力:
File .text Size Crate Name
2.4% 3.0% 47.0KiB std <std macros>
1.8% 2.3% 35.5KiB myapp myapp::heavy_module::process
1.2% 1.5% 23.1KiB serde serde::de::...
4. cargo-llvm-lines によるモノモーフィゼーションの肥大化
# Install
cargo install cargo-llvm-lines
# Show LLVM IR line counts (proxy for monomorphization)
cargo llvm-lines --release | head -40
# Filter to your crate only
cargo llvm-lines --release | grep '^myapp'
一般的な出力:
Lines Copies Function name
85330 1 [LLVM passes]
7761 92 core::fmt::write
4672 11 myapp::process::<impl MyTrait for T>
3201 47 <alloc::vec::Vec<T> as core::ops::Drop>::drop
Copies の数が多い場合は、モノモーフィゼーションによるコードの展開を示しています。対処方法:
// Before: generic, gets monomorphized for every T
fn process<T: AsRef<[u8]>>(data: T) -> usize {
do_work(data.as_ref())
}
// After: thin generic wrapper + concrete inner
fn process<T: AsRef<[u8]>>(data: T) -> usize {
fn inner(data: &[u8]) -> usize { do_work(data) }
inner(data.as_ref())
}
5. Criterion のマイクロベンチマーク
# Cargo.toml
[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
[[bench]]
name = "my_bench"
harness = false
// benches/my_bench.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
fn bench_process(c: &mut Criterion) {
// Simple benchmark
c.bench_function("process 1000 items", |b| {
let data: Vec<i32> = (0..1000).collect();
b.iter(|| process(black_box(&data))) // black_box prevents optimization
});
}
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);
# Run all benchmarks
cargo bench
# Run specific benchmark
cargo bench --bench my_bench
# Run with filter
cargo bench -- process_sizes
# Compare with baseline (save/load)
cargo bench -- --save-baseline before
# make changes
cargo bench -- --baseline before
# View HTML report
open target/criterion/report/index.html
6. Rust での perf(Linux)
# Record
perf record -g ./target/release-with-debug/myapp args
perf record -g -F 999 ./target/release-with-debug/myapp args # higher freq
# Report
perf report # interactive TUI
perf report --stdio --no-call-graph | head -40 # text
# Annotate specific function
perf annotate myapp::hot_function
# stat (quick counters)
perf stat ./target/release/myapp args
Rust 固有の perf に関するヒント:
debug = 1(行テーブルのみ)でビルドすると、行単位の帰属情報を維持しながらビルドを高速化できますRUSTFLAGS="-C force-frame-pointers=yes"を使用すると、DWARF のアンワインドなしで、より優れた呼び出しグラフを取得できます- 再現可能なアドレスにするには、ASLR を無効にします:
setarch $(uname -m) -R ./myapp
7. 割り当てのための heaptrack / DHAT
# heaptrack (Linux)
heaptrack ./target/release/myapp args
heaptrack_print heaptrack.myapp.*.zst | head -50
# DHAT via Valgrind
valgrind --tool=dhat ./target/debug/myapp args
# Open dhat-out.* with dh_view.html
フレームグラフのセットアップと Criterion の設定については、references/cargo-flamegraph-setup.md を参照してください。
関連スキル
- ビルド設定(デバッグシンボル、プロファイル)については、
skills/rust/rustc-basicsを使用します - perf の基本については、
skills/profilers/linux-perfを使用します - フレームグラフの SVG の読み取りと解釈については、
skills/profilers/flamegraphsを使用します - massif/DHAT による割り当てのプロファイリングについては、
skills/profilers/valgrindを使用します
コメント
Markdown 対応