Skip to main content

big_group/
big-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    let insns = Builder::new()
27        .group(&mut group)
28        .kind(Hardware::INSTRUCTIONS)
29        .build()?;
30    let cycles = Builder::new()
31        .group(&mut group)
32        .kind(Hardware::CPU_CYCLES)
33        .build()?;
34
35    // Note that if you add more counters than you actually have hardware for,
36    // the kernel will time-slice them, which means you may get no coverage for
37    // short measurements. See the documentation.
38    //
39    // On my machine, this program won't collect any data unless I disable the
40    // NMI watchdog, as described in the documentation for `Group`. My machine
41    // has four counters, and this program tries to use all of them, but the NMI
42    // watchdog uses one up.
43
44    let mut vec = (0..=100000).collect::<Vec<_>>();
45
46    group.enable()?;
47    vec.sort();
48    println!("{:?}", &vec[0..10]);
49    group.disable()?;
50
51    let counts = group.read()?;
52
53    println!(
54        "enabled for {}ns, actually running for {}ns",
55        counts.time_enabled(),
56        counts.time_running()
57    );
58
59    if counts.time_running() == 0 {
60        println!("Group was never running; no results available.");
61        return Ok(());
62    }
63
64    if counts.time_running() < counts.time_enabled() {
65        println!("Counts cover only a portion of the execution.");
66    }
67
68    println!(
69        "L1D cache misses/references: {} / {} ({:.0}%)",
70        counts[&miss_counter],
71        counts[&access_counter],
72        (counts[&miss_counter] as f64 / counts[&access_counter] as f64) * 100.0
73    );
74
75    println!(
76        "branch prediction misses/total: {} / {} ({:.0}%)",
77        counts[&missed_branches],
78        counts[&branches],
79        (counts[&missed_branches] as f64 / counts[&branches] as f64) * 100.0
80    );
81
82    println!(
83        "{} instructions, {} cycles ({:.2} cpi)",
84        counts[&insns],
85        counts[&cycles],
86        counts[&cycles] as f64 / counts[&insns] as f64
87    );
88
89    // You can iterate over a `Counts` value:
90    for (id, value) in &counts {
91        println!("Counter id {} has value {}", id, value);
92    }
93
94    Ok(())
95}