perf_event/events/cache.rs
1use c_enum::c_enum;
2use perf_event_open_sys::bindings;
3
4use crate::events::Event;
5
6/// A cache event.
7///
8/// A cache event has three identifying characteristics:
9///
10/// - which cache to observe ([`which`])
11///
12/// - what sort of request it's handling ([`operation`])
13///
14/// - whether we want to count all cache accesses, or just misses ([`result`]).
15///
16/// For example, to measure the L1 data cache's miss rate:
17///
18/// ```
19/// # use perf_event::{Builder, Group};
20/// # use perf_event::events::{Cache, CacheOp, CacheResult, Hardware, WhichCache};
21/// # fn main() -> std::io::Result<()> {
22/// // A `Cache` value representing L1 data cache read accesses.
23/// const ACCESS: Cache = Cache {
24/// which: WhichCache::L1D,
25/// operation: CacheOp::READ,
26/// result: CacheResult::ACCESS,
27/// };
28///
29/// // A `Cache` value representing L1 data cache read misses.
30/// const MISS: Cache = Cache {
31/// result: CacheResult::MISS,
32/// ..ACCESS
33/// };
34///
35/// // Construct a `Group` containing the two new counters, from which we
36/// // can get counts over matching periods of time.
37/// let mut group = Group::new()?;
38/// let access_counter = group.add(&Builder::new(ACCESS))?;
39/// let miss_counter = group.add(&Builder::new(MISS))?;
40/// # Ok(()) }
41/// ```
42///
43/// [`which`]: enum.WhichCache.html
44/// [`operation`]: enum.CacheOp.html
45/// [`result`]: enum.CacheResult.html
46#[derive(Debug, Clone, Eq, PartialEq)]
47pub struct Cache {
48 /// Which cache is being monitored? (data, instruction, ...)
49 pub which: CacheId,
50
51 /// What operation is being monitored? (read, write, etc.)
52 pub operation: CacheOp,
53
54 /// All accesses, or just misses?
55 pub result: CacheResult,
56}
57
58impl Cache {
59 fn as_config(&self) -> u64 {
60 self.which.0 as u64 | ((self.operation.0 as u64) << 8) | ((self.result.0 as u64) << 16)
61 }
62}
63
64impl Event for Cache {
65 fn update_attrs(self, attr: &mut bindings::perf_event_attr) {
66 attr.type_ = bindings::PERF_TYPE_HW_CACHE;
67 attr.config = self.as_config()
68 }
69}
70
71#[doc(hidden)]
72#[deprecated = "WhichCache has been renamed to CacheId"]
73pub type WhichCache = CacheId;
74
75c_enum! {
76 /// A cache whose events we would like to count.
77 ///
78 /// This is used in the `Cache` type as part of the identification of a cache
79 /// event. Each variant here corresponds to a particular
80 /// `PERF_COUNT_HW_CACHE_...` constant supported by the [`perf_event_open`][man]
81 /// system call.
82 ///
83 /// [man]: https://www.mankier.com/2/perf_event_open
84 #[repr(transparent)]
85 #[derive(Clone, Copy, Eq, PartialEq, Hash)]
86 pub enum CacheId : u8 {
87 /// Level 1 data cache.
88 L1D = bindings::PERF_COUNT_HW_CACHE_L1D as _,
89
90 /// Level 1 instruction cache.
91 L1I = bindings::PERF_COUNT_HW_CACHE_L1I as _,
92
93 /// Last-level cache.
94 LL = bindings::PERF_COUNT_HW_CACHE_LL as _,
95
96 /// Data translation lookaside buffer (virtual address translation).
97 DTLB = bindings::PERF_COUNT_HW_CACHE_DTLB as _,
98
99 /// Instruction translation lookaside buffer (virtual address translation).
100 ITLB = bindings::PERF_COUNT_HW_CACHE_ITLB as _,
101
102 /// Branch prediction.
103 BPU = bindings::PERF_COUNT_HW_CACHE_BPU as _,
104
105 /// Memory accesses that stay local to the originating NUMA node.
106 NODE = bindings::PERF_COUNT_HW_CACHE_NODE as _,
107 }
108}
109
110c_enum! {
111 /// What sort of cache operation we would like to observe.
112 ///
113 /// This is used in the `Cache` type as part of the identification of a cache
114 /// event. Each variant here corresponds to a particular
115 /// `PERF_COUNT_HW_CACHE_OP_...` constant supported by the
116 /// [`perf_event_open`][man] system call.
117 ///
118 /// [man]: https://www.mankier.com/2/perf_event_open
119 #[repr(transparent)]
120 #[derive(Clone, Copy, Eq, PartialEq, Hash)]
121 pub enum CacheOp : u8 {
122 /// Read accesses.
123 READ = bindings::PERF_COUNT_HW_CACHE_OP_READ as _,
124
125 /// Write accesses.
126 WRITE = bindings::PERF_COUNT_HW_CACHE_OP_WRITE as _,
127
128 /// Prefetch accesses.
129 PREFETCH = bindings::PERF_COUNT_HW_CACHE_OP_PREFETCH as _,
130 }
131}
132
133c_enum! {
134 /// What sort of cache result we're interested in observing.
135 ///
136 /// `ACCESS` counts the total number of operations performed on the cache,
137 /// whereas `MISS` counts only those requests that the cache could not satisfy.
138 /// Treating `MISS` as a fraction of `ACCESS` gives you the cache's miss rate.
139 ///
140 /// This is used used in the `Cache` type as part of the identification of a
141 /// cache event. Each variant here corresponds to a particular
142 /// `PERF_COUNT_HW_CACHE_RESULT_...` constant supported by the
143 /// [`perf_event_open`][man] system call.
144 ///
145 /// [man]: https://www.mankier.com/2/perf_event_open
146 #[repr(transparent)]
147 #[derive(Clone, Copy, Eq, PartialEq, Hash)]
148 pub enum CacheResult : u8 {
149 /// Cache was accessed.
150 ACCESS = bindings::PERF_COUNT_HW_CACHE_RESULT_ACCESS as _,
151
152 /// Cache access was a miss.
153 MISS = bindings::PERF_COUNT_HW_CACHE_RESULT_MISS as _,
154 }
155}