Rust性能分析库criterion-perf-events的使用:基于perf事件的基准测试与性能监控工具
Rust性能分析库criterion-perf-events的使用:基于perf事件的基准测试与性能监控工具
Criterion-perf-events
这是一个用于Criterion.rs的测量插件,用于测量Linux perf接口的事件。
支持的事件
Criterion-perf-events使用perfcnt crate并支持该crate提供的事件。如果您想了解更详细的信息,请查看以下列出的事件:
- 硬件事件
- 软件事件
- Perf事件
- 原始Intel事件
故障排除
如果您遇到"Permission denied"错误,请更新perf_event_paranoid
:
sudo sh -c 'echo 1 >/proc/sys/kernel/perf_event_paranoid'
示例
以下代码展示了如何计算退休指令(retired instructions)。
use criterion::{criterion_group, criterion_main, BenchmarkId, black_box, Criterion};
use criterion_perf_events::Perf;
use perfcnt::linux::HardwareEventType as Hardware;
use perfcnt::linux::PerfCounterBuilderLinux as Builder;
fn fibonacci_slow(n: usize) -> usize {
match n {
0 => 1,
1 => 1,
n => fibonacci_slow(n - 1) + fibonacci_slow(n - 2),
}
}
fn bench(c: &mut Criterion<Perf>) {
let mut group = c.benchmark_group("fibonacci");
let fibo_arg = 30;
group.bench_function(BenchmarkId::new("slow", fibo_arg), |b| {
b.iter(|| fibonacci_slow(black_box(fibo_arg)))
});
group.finish()
}
criterion_group!(
name = instructions_bench;
config = Criterion::default().with_measurement(Perf::new(Builder::from_hardware_event(Hardware::Instructions)));
targets = bench
);
criterion_main!(instructions_bench);
运行命令:
cargo criterion
打开target/criterion/reports/index.html
查看带有图表的详细结果。对于所有事件类型(Hardware::Instructions
、Hardware::CacheMisses
等),criterion总是报告周期作为单位。请注意,显示的是您的事件类型,而不是CPU周期。
完整示例
// 添加以下依赖到Cargo.toml:
// [dev-dependencies]
// criterion = "0.3"
// criterion-perf-events = "0.4"
// perfcnt = "0.5"
use criterion::{criterion_group, criterion_main, BenchmarkId, black_box, Criterion};
use criterion_perf_events::Perf;
use perfcnt::linux::HardwareEventType as Hardware;
use perfcnt::linux::PerfCounterBuilderLinux as Builder;
// 定义一个简单的递归斐波那契函数用于测试
fn fibonacci_slow(n: usize) -> usize {
match n {
0 => 1,
1 => 1,
n => fibonacci_slow(n - 1) + fibonacci_slow(n - 2),
}
}
// 基准测试函数
fn bench(c: &mut Criterion<Perf>) {
let mut group = c.benchmark_group("fibonacci");
// 测试参数
let fibo_arg = 30;
// 添加基准测试案例
group.bench_function(BenchmarkId::new("slow", fibo_arg), |b| {
b.iter(|| fibonacci_slow(black_box(fibo_arg)))
});
group.finish()
}
// 配置基准测试组
criterion_group!(
name = instructions_bench;
config = Criterion::default().with_measurement(
Perf::new(Builder::from_hardware_event(Hardware::Instructions))
);
targets = bench
);
// 主函数入口
criterion_main!(instructions_bench);
这个示例展示了如何使用criterion-perf-events来测量斐波那契计算中的指令数。关键点包括:
- 使用
Perf
作为测量插件 - 配置
Hardware::Instructions
作为要测量的硬件事件 - 通过
cargo criterion
运行基准测试 - 结果会显示在HTML报告中
您可以根据需要更改硬件事件类型,例如使用Hardware::CacheMisses
来测量缓存未命中次数。
1 回复
Rust性能分析库criterion-perf-events的使用指南
完整示例demo
下面是一个结合了基础使用、多事件测量和自定义配置的完整示例:
// 导入必要的库
use criterion::{criterion_group, criterion_main, Criterion};
use criterion_perf_events::Perf;
use perfcnt::linux::{HardwareEventType as Hardware, SoftwareEventType as Software};
use perfcnt::linux::PerfCounterBuilderLinux as Builder;
// 定义一个简单的计算函数用于测试
fn compute_heavy(n: u64) -> u64 {
(0..n).fold(0, |acc, x| acc + x * x)
}
// 基准测试函数
fn benchmark(c: &mut Criterion<Perf>) {
// 测试1: 测量CPU周期和指令数
let mut group1 = c.benchmark_group("basic_metrics");
group1.with_perf_event(Builder::from_hardware_event(Hardware::CPUCycles));
group1.with_perf_event(Builder::from_hardware_event(Hardware::Instructions));
group1.bench_function("compute 1000", |b| b.iter(|| compute_heavy(1000)));
group1.finish();
// 测试2: 测量缓存相关指标
let mut group2 = c.benchmark_group("cache_metrics");
group2.with_perf_event(
Builder::from_hardware_event(Hardware::CacheReferences)
.exclude_kernel()
.exclude_hv()
);
group2.with_perf_event(Builder::from_hardware_event(Hardware::CacheMisses));
group2.bench_function("compute 5000", |b| b.iter(|| compute_heavy(5000)));
group2.finish();
// 测试3: 组合硬件和软件事件
let mut group3 = c.benchmark_group("combined_metrics");
group3.with_perf_event(Builder::from_hardware_event(Hardware::BranchMisses));
group3.with_perf_event(Builder::from_software_event(Software::PageFaults));
group3.bench_function("compute 10000", |b| b.iter(|| compute_heavy(10000)));
group3.finish();
}
// 配置基准测试组
criterion_group! {
name = benches;
config = Criterion::default().with_measurement(Perf);
targets = benchmark
}
// 主函数
criterion_main!(benches);
示例说明
-
这个示例展示了三种不同的测试场景:
- 基本CPU指标测量(周期和指令数)
- 缓存相关指标测量
- 混合硬件和软件事件测量
-
每个测试组都配置了不同的事件组合,并测试同一个计算函数在不同输入大小下的性能
-
使用了自定义配置来排除内核和hypervisor事件,以获得更精确的用户空间测量结果
预期输出示例
运行上述基准测试后,输出会类似如下格式:
basic_metrics/compute 1000
time: [123.45 us 124.56 us 125.67 us]
CPUCycles: [456789 467890 478901]
Instructions: [1234567 1245678 1256789]
cache_metrics/compute 5000
time: [678.90 us 689.01 us 699.12 us]
CacheReferences: [12345 12456 12567]
CacheMisses: [123 124 125]
combined_metrics/compute 10000
time: [1.234 ms 1.245 ms 1.256 ms]
BranchMisses: [456 467 478]
PageFaults: [12 13 14]