pub struct Counts { /* private fields */ }Expand description
A collection of counts from a Group of counters.
This is the type returned by calling read on a Group.
You can index it with a reference to a specific Counter:
let counts = group.read()?;
println!("cycles / instructions: {} / {} ({:.2} cpi)",
counts[&cycles],
counts[&insns],
(counts[&cycles] as f64 / counts[&insns] as f64));Or you can iterate over the results it contains:
for (id, value) in &counts {
println!("Counter id {} has value {}", id, value);
}The id values produced by this iteration are internal identifiers assigned
by the kernel. You can use the Counter::id method to find a
specific counter’s id.
For some kinds of events, the kernel may use timesharing to give all
counters access to scarce hardware registers. You can see how long a group
was actually running versus the entire time it was enabled using the
time_enabled and time_running methods:
let scale = counts.time_enabled() as f64 /
counts.time_running() as f64;
for (id, value) in &counts {
print!("Counter id {} has value {}",
id, (*value as f64 * scale) as u64);
if scale > 1.0 {
print!(" (estimated)");
}
println!();
}
Implementations§
Source§impl Counts
impl Counts
Sourcepub fn time_enabled(&self) -> u64
pub fn time_enabled(&self) -> u64
Return the number of nanoseconds the Group was enabled that
contributed to this Counts’ contents.
Examples found in repository?
84fn measure(label: &str, task: impl FnOnce()) {
85 use perf_event::events::{Cache, CacheOp, CacheResult, WhichCache};
86 use perf_event::{Builder, Group};
87
88 let mut group = Group::new().expect("creating group is ok");
89 let read_counter = Builder::new()
90 .group(&mut group)
91 .kind(Cache {
92 which: WhichCache::L1D,
93 operation: CacheOp::READ,
94 result: CacheResult::ACCESS,
95 })
96 .build()
97 .expect("building read_counter is ok");
98 let read_miss_counter = Builder::new()
99 .group(&mut group)
100 .kind(Cache {
101 which: WhichCache::L1D,
102 operation: CacheOp::READ,
103 result: CacheResult::MISS,
104 })
105 .build()
106 .expect("building read_miss_counter is ok");
107 let prefetch_counter = Builder::new()
108 .group(&mut group)
109 .kind(Cache {
110 which: WhichCache::L1D,
111 operation: CacheOp::PREFETCH,
112 result: CacheResult::ACCESS,
113 })
114 .build()
115 .expect("building prefetch_counter is ok");
116
117 group.enable().expect("enabling group is ok");
118 task();
119 group.disable().expect("disabling group is ok");
120
121 let counts = group.read().expect("reading group is ok");
122 let reads = counts[&read_counter];
123 let read_misses = counts[&read_miss_counter];
124 let read_hits = reads - read_misses;
125 let prefetches = counts[&prefetch_counter];
126
127 println!(
128 "{label}: hits / reads: {read_hits:8} / {reads:8} {:6.2}%, \
129 prefetched {prefetches:8}",
130 (read_hits as f64 / reads as f64) * 100.0,
131 );
132
133 if counts.time_enabled() != counts.time_running() {
134 println!(
135 "time enabled: {} time running: {}",
136 counts.time_enabled(),
137 counts.time_running(),
138 );
139 }
140}More examples
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}Sourcepub fn time_running(&self) -> u64
pub fn time_running(&self) -> u64
Return the number of nanoseconds the Group was actually collecting
counts that contributed to this Counts’ contents.
Examples found in repository?
84fn measure(label: &str, task: impl FnOnce()) {
85 use perf_event::events::{Cache, CacheOp, CacheResult, WhichCache};
86 use perf_event::{Builder, Group};
87
88 let mut group = Group::new().expect("creating group is ok");
89 let read_counter = Builder::new()
90 .group(&mut group)
91 .kind(Cache {
92 which: WhichCache::L1D,
93 operation: CacheOp::READ,
94 result: CacheResult::ACCESS,
95 })
96 .build()
97 .expect("building read_counter is ok");
98 let read_miss_counter = Builder::new()
99 .group(&mut group)
100 .kind(Cache {
101 which: WhichCache::L1D,
102 operation: CacheOp::READ,
103 result: CacheResult::MISS,
104 })
105 .build()
106 .expect("building read_miss_counter is ok");
107 let prefetch_counter = Builder::new()
108 .group(&mut group)
109 .kind(Cache {
110 which: WhichCache::L1D,
111 operation: CacheOp::PREFETCH,
112 result: CacheResult::ACCESS,
113 })
114 .build()
115 .expect("building prefetch_counter is ok");
116
117 group.enable().expect("enabling group is ok");
118 task();
119 group.disable().expect("disabling group is ok");
120
121 let counts = group.read().expect("reading group is ok");
122 let reads = counts[&read_counter];
123 let read_misses = counts[&read_miss_counter];
124 let read_hits = reads - read_misses;
125 let prefetches = counts[&prefetch_counter];
126
127 println!(
128 "{label}: hits / reads: {read_hits:8} / {reads:8} {:6.2}%, \
129 prefetched {prefetches:8}",
130 (read_hits as f64 / reads as f64) * 100.0,
131 );
132
133 if counts.time_enabled() != counts.time_running() {
134 println!(
135 "time enabled: {} time running: {}",
136 counts.time_enabled(),
137 counts.time_running(),
138 );
139 }
140}More examples
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}Source§impl Counts
impl Counts
Sourcepub fn get(&self, member: &Counter) -> Option<&u64>
pub fn get(&self, member: &Counter) -> Option<&u64>
Return the value recorded for member in self, or None if member
is not present.
If you know that member is in the group, you can simply index:
let cycles = counts[&cycle_counter];Sourcepub fn iter<'a>(&'a self) -> CountsIter<'a> ⓘ
pub fn iter<'a>(&'a self) -> CountsIter<'a> ⓘ
Return an iterator over the counts in self.
for (id, value) in &counts {
println!("Counter id {} has value {}", id, value);
}Each item is a pair (id, &value), where id is the number assigned to
the counter by the kernel (see Counter::id), and value is that
counter’s value.