Skip to main content

group/
group.rs

1use perf_event::events::{Cache, CacheOp, CacheResult, Hardware, WhichCache};
2use perf_event::{Builder, Group};
3
4fn main() -> std::io::Result<()> {
5    const ACCESS: Cache = Cache {
6        which: WhichCache::L1D,
7        operation: CacheOp::READ,
8        result: CacheResult::ACCESS,
9    };
10    const MISS: Cache = Cache {
11        result: CacheResult::MISS,
12        ..ACCESS
13    };
14
15    let mut group = Group::new()?;
16    let access_counter = Builder::new().group(&mut group).kind(ACCESS).build()?;
17    let miss_counter = Builder::new().group(&mut group).kind(MISS).build()?;
18    let branches = Builder::new()
19        .group(&mut group)
20        .kind(Hardware::BRANCH_INSTRUCTIONS)
21        .build()?;
22    let missed_branches = Builder::new()
23        .group(&mut group)
24        .kind(Hardware::BRANCH_MISSES)
25        .build()?;
26
27    // Note that if you add more counters than you actually have hardware for,
28    // the kernel will time-slice them, which means you may get no coverage for
29    // short measurements. See the documentation.
30
31    let vec = (0..=51).collect::<Vec<_>>();
32
33    group.enable()?;
34    println!("{:?}", vec);
35    group.disable()?;
36
37    let counts = group.read()?;
38    println!(
39        "L1D cache misses/references: {} / {} ({:.0}%)",
40        counts[&miss_counter],
41        counts[&access_counter],
42        (counts[&miss_counter] as f64 / counts[&access_counter] as f64) * 100.0
43    );
44
45    println!(
46        "branch prediction misses/total: {} / {} ({:.0}%)",
47        counts[&missed_branches],
48        counts[&branches],
49        (counts[&missed_branches] as f64 / counts[&branches] as f64) * 100.0
50    );
51
52    // You can iterate over a `Counts` value:
53    for (id, value) in &counts {
54        println!("Counter id {} has value {}", id, value);
55    }
56
57    Ok(())
58}