]> git.proxmox.com Git - rustc.git/blame - vendor/perf-event/src/events.rs
New upstream version 1.48.0+dfsg1
[rustc.git] / vendor / perf-event / src / events.rs
CommitLineData
3dfed10e
XL
1//! Events we can monitor or count.
2//!
3//! There are three general categories of event:
4//!
5//! - [`Hardware`] events are counted by the processor itself. This
6//! includes things like clock cycles, instructions retired, and cache and
7//! branch prediction statistics.
8//!
9//! - [`Software`] events are counted by the kernel. This includes things
10//! like context switches, page faults, and so on.
11//!
12//! - [`Cache`] events offer a more detailed view of the processor's cache
13//! counters. You can select which level of the cache hierarchy to observe,
14//! discriminate between data and instruction caches, and so on.
15//!
16//! The `Event` type is just an enum with a variant for each of the above types,
17//! which all implement `Into<Event>`.
18//!
19//! Linux supports many more kinds of events than this module covers, including
20//! events specific to particular make and model of processor, and events that
21//! are dynamically registered by drivers and kernel modules. If something you
22//! want is missing, think about the best API to expose it, and submit a pull
23//! request!
24//!
25//! [`Hardware`]: enum.Hardware.html
26//! [`Software`]: enum.Software.html
27//! [`Cache`]: struct.Cache.html
28
29#![allow(non_camel_case_types)]
30use perf_event_open_sys::bindings as bindings;
31
32/// Any sort of event. This is a sum of the [`Hardware`],
33/// [`Software`], and [`Cache`] types, which all implement
34/// `Into<Event>`.
35///
36/// [`Hardware`]: enum.Hardware.html
37/// [`Software`]: enum.Software.html
38/// [`Cache`]: struct.Cache.html
39#[derive(Clone, Debug, Eq, PartialEq)]
40pub enum Event {
41 #[allow(missing_docs)]
42 Hardware(Hardware),
43
44 #[allow(missing_docs)]
45 Software(Software),
46
47 #[allow(missing_docs)]
48 Cache(Cache),
49}
50
51impl Event {
52 pub(crate) fn as_type(&self) -> bindings::perf_type_id {
53 match self {
54 Event::Hardware(_) => bindings::perf_type_id_PERF_TYPE_HARDWARE,
55 Event::Software(_) => bindings::perf_type_id_PERF_TYPE_SOFTWARE,
56 Event::Cache(_) => bindings::perf_type_id_PERF_TYPE_HW_CACHE,
57 }
58 }
59
60 pub(crate) fn as_config(self) -> u64 {
61 match self {
62 Event::Hardware(hw) => hw as _,
63 Event::Software(sw) => sw as _,
64 Event::Cache(cache) => cache.as_config(),
65 }
66 }
67}
68
69/// Hardware counters.
70///
71/// These are counters implemented by the processor itself. Such counters vary
72/// from one architecture to the next, and even different models within a
73/// particular architecture will often change the way they expose this data.
74/// This is a selection of portable names for values that can be obtained on a
75/// wide variety of systems.
76///
77/// Each variant of this enum corresponds to a particular `PERF_COUNT_HW_`...
78/// value supported by the [`perf_event_open`][man] system call.
79///
80/// [man]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
81#[repr(u32)]
82#[derive(Copy, Clone, Debug, Eq, PartialEq)]
83pub enum Hardware {
84 /// Total cycles. Be wary of what happens during CPU frequency scaling.
85 CPU_CYCLES = bindings::perf_hw_id_PERF_COUNT_HW_CPU_CYCLES,
86
87 /// Retired instructions. Be careful, these can be affected by various
88 /// issues, most notably hardware interrupt counts.
89 INSTRUCTIONS = bindings::perf_hw_id_PERF_COUNT_HW_INSTRUCTIONS,
90
91 /// Cache accesses. Usually this indicates Last Level Cache accesses but
92 /// this may vary depending on your CPU. This may include prefetches and
93 /// coherency messages; again this depends on the design of your CPU.
94 CACHE_REFERENCES = bindings::perf_hw_id_PERF_COUNT_HW_CACHE_REFERENCES,
95
96 /// Cache misses. Usually this indicates Last Level Cache misses; this is
97 /// intended to be used in conjunction with the
98 /// PERF_COUNT_HW_CACHE_REFERENCES event to calculate cache miss rates.
99 CACHE_MISSES = bindings::perf_hw_id_PERF_COUNT_HW_CACHE_MISSES,
100
101 /// Retired branch instructions. Prior to Linux 2.6.35, this used the wrong
102 /// event on AMD processors.
103 BRANCH_INSTRUCTIONS = bindings::perf_hw_id_PERF_COUNT_HW_BRANCH_INSTRUCTIONS,
104
105 /// Mispredicted branch instructions.
106 BRANCH_MISSES = bindings::perf_hw_id_PERF_COUNT_HW_BRANCH_MISSES,
107
108 /// Bus cycles, which can be different from total cycles.
109 BUS_CYCLES = bindings::perf_hw_id_PERF_COUNT_HW_BUS_CYCLES,
110
111 /// Stalled cycles during issue. (since Linux 3.0)
112 STALLED_CYCLES_FRONTEND = bindings::perf_hw_id_PERF_COUNT_HW_STALLED_CYCLES_FRONTEND,
113
114 /// Stalled cycles during retirement. (since Linux 3.0)
115 STALLED_CYCLES_BACKEND = bindings::perf_hw_id_PERF_COUNT_HW_STALLED_CYCLES_BACKEND,
116
117 /// Total cycles; not affected by CPU frequency scaling. (since Linux 3.3)
118 REF_CPU_CYCLES = bindings::perf_hw_id_PERF_COUNT_HW_REF_CPU_CYCLES,
119}
120
121impl From<Hardware> for Event {
122 fn from(hw: Hardware) -> Event {
123 Event::Hardware(hw)
124 }
125}
126
127/// Software counters, implemented by the kernel.
128///
129/// Each variant of this enum corresponds to a particular `PERF_COUNT_SW_`...
130/// value supported by the [`perf_event_open`][man] system call.
131///
132/// [man]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
133#[repr(u32)]
134#[derive(Copy, Clone, Debug, Eq, PartialEq)]
135pub enum Software {
136 /// This reports the CPU clock, a high-resolution per-CPU timer.
137 CPU_CLOCK = bindings::perf_sw_ids_PERF_COUNT_SW_CPU_CLOCK,
138
139 /// This reports a clock count specific to the task that is running.
140 TASK_CLOCK = bindings::perf_sw_ids_PERF_COUNT_SW_TASK_CLOCK,
141
142 /// This reports the number of page faults.
143 PAGE_FAULTS = bindings::perf_sw_ids_PERF_COUNT_SW_PAGE_FAULTS,
144
145 /// This counts context switches. Until Linux 2.6.34, these were all
146 /// reported as user-space events, after that they are reported as happening
147 /// in the kernel.
148 CONTEXT_SWITCHES = bindings::perf_sw_ids_PERF_COUNT_SW_CONTEXT_SWITCHES,
149
150 /// This reports the number of times the process has migrated to a new CPU.
151 CPU_MIGRATIONS = bindings::perf_sw_ids_PERF_COUNT_SW_CPU_MIGRATIONS,
152
153 /// This counts the number of minor page faults. These did not require disk
154 /// I/O to handle.
155 PAGE_FAULTS_MIN = bindings::perf_sw_ids_PERF_COUNT_SW_PAGE_FAULTS_MIN,
156
157 /// This counts the number of major page faults. These required disk I/O to
158 /// handle.
159 PAGE_FAULTS_MAJ = bindings::perf_sw_ids_PERF_COUNT_SW_PAGE_FAULTS_MAJ,
160
161 /// (since Linux 2.6.33) This counts the number of alignment faults. These
162 /// happen when unaligned memory accesses happen; the kernel can handle
163 /// these but it reduces performance. This happens only on some
164 /// architectures (never on x86).
165 ALIGNMENT_FAULTS = bindings::perf_sw_ids_PERF_COUNT_SW_ALIGNMENT_FAULTS,
166
167 /// (since Linux 2.6.33) This counts the number of emulation faults. The
168 /// kernel sometimes traps on unimplemented instructions and emulates them
169 /// for user space. This can negatively impact performance.
170 EMULATION_FAULTS = bindings::perf_sw_ids_PERF_COUNT_SW_EMULATION_FAULTS,
171
172 /// (since Linux 3.12) This is a placeholder event that counts nothing.
173 /// Informational sample record types such as mmap or comm must be
174 /// associated with an active event. This dummy event allows gathering such
175 /// records without requiring a counting event.
176 DUMMY = bindings::perf_sw_ids_PERF_COUNT_SW_DUMMY,
177}
178
179impl From<Software> for Event {
180 fn from(hw: Software) -> Event {
181 Event::Software(hw)
182 }
183}
184
185/// A cache event.
186///
187/// A cache event has three identifying characteristics:
188///
189/// - which cache to observe ([`which`])
190///
191/// - what sort of request it's handling ([`operation`])
192///
193/// - whether we want to count all cache accesses, or just misses
194/// ([`result`]).
195///
196/// For example, to measure the L1 data cache's miss rate:
197///
198/// # use perf_event::{Builder, Group};
199/// # use perf_event::events::{Cache, CacheOp, CacheResult, Hardware, WhichCache};
200/// # fn main() -> std::io::Result<()> {
201/// // A `Cache` value representing L1 data cache read accesses.
202/// const ACCESS: Cache = Cache {
203/// which: WhichCache::L1D,
204/// operation: CacheOp::READ,
205/// result: CacheResult::ACCESS,
206/// };
207///
208/// // A `Cache` value representing L1 data cache read misses.
209/// const MISS: Cache = Cache { result: CacheResult::MISS, ..ACCESS };
210///
211/// // Construct a `Group` containing the two new counters, from which we
212/// // can get counts over matching periods of time.
213/// let mut group = Group::new()?;
214/// let access_counter = Builder::new().group(&mut group).kind(ACCESS).build()?;
215/// let miss_counter = Builder::new().group(&mut group).kind(MISS).build()?;
216/// # Ok(()) }
217///
218/// [`which`]: enum.WhichCache.html
219/// [`operation`]: enum.CacheOp.html
220/// [`result`]: enum.CacheResult.html
221#[derive(Debug, Clone, Eq, PartialEq)]
222pub struct Cache {
223 /// Which cache is being monitored? (data, instruction, ...)
224 pub which: WhichCache,
225
226 /// What operation is being monitored? (read, write, etc.)
227 pub operation: CacheOp,
228
229 /// All accesses, or just misses?
230 pub result: CacheResult,
231}
232
233impl From<Cache> for Event {
234 fn from(hw: Cache) -> Event {
235 Event::Cache(hw)
236 }
237}
238
239impl Cache {
240 fn as_config(&self) -> u64 {
241 self.which as u64 |
242 ((self.operation as u64) << 8) |
243 ((self.result as u64) << 16)
244 }
245}
246
247/// A cache whose events we would like to count.
248///
249/// This is used in the `Cache` type as part of the identification of a cache
250/// event. Each variant here corresponds to a particular
251/// `PERF_COUNT_HW_CACHE_...` constant supported by the [`perf_event_open`][man]
252/// system call.
253///
254/// [man]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
255#[repr(u32)]
256#[derive(Debug, Clone, Copy, Eq, PartialEq)]
257pub enum WhichCache {
258 /// for measuring Level 1 Data Cache
259 L1D = bindings::perf_hw_cache_id_PERF_COUNT_HW_CACHE_L1D,
260
261 /// for measuring Level 1 Instruction Cache
262 L1I = bindings::perf_hw_cache_id_PERF_COUNT_HW_CACHE_L1I,
263
264 /// for measuring Last-Level Cache
265 LL = bindings::perf_hw_cache_id_PERF_COUNT_HW_CACHE_LL,
266
267 /// for measuring the Data TLB
268 DTLB = bindings::perf_hw_cache_id_PERF_COUNT_HW_CACHE_DTLB,
269
270 /// for measuring the Instruction TLB
271 ITLB = bindings::perf_hw_cache_id_PERF_COUNT_HW_CACHE_ITLB,
272
273 /// for measuring the branch prediction unit
274 BPU = bindings::perf_hw_cache_id_PERF_COUNT_HW_CACHE_BPU,
275
276 /// (since Linux 3.1) for measuring local memory accesses
277 NODE = bindings::perf_hw_cache_id_PERF_COUNT_HW_CACHE_NODE,
278}
279
280/// What sort of cache operation we would like to observe.
281///
282/// This is used in the `Cache` type as part of the identification of a cache
283/// event. Each variant here corresponds to a particular
284/// `PERF_COUNT_HW_CACHE_OP_...` constant supported by the
285/// [`perf_event_open`][man] system call.
286///
287/// [man]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
288#[repr(u32)]
289#[derive(Debug, Clone, Copy, Eq, PartialEq)]
290pub enum CacheOp {
291 /// Read accesses.
292 READ = bindings::perf_hw_cache_op_id_PERF_COUNT_HW_CACHE_OP_READ,
293
294 /// Write accesses.
295 WRITE = bindings::perf_hw_cache_op_id_PERF_COUNT_HW_CACHE_OP_WRITE,
296
297 /// Prefetch accesses.
298 PREFETCH = bindings::perf_hw_cache_op_id_PERF_COUNT_HW_CACHE_OP_PREFETCH,
299}
300
301#[repr(u32)]
302/// What sort of cache result we're interested in observing.
303///
304/// `ACCESS` counts the total number of operations performed on the cache,
305/// whereas `MISS` counts only those requests that the cache could not satisfy.
306/// Treating `MISS` as a fraction of `ACCESS` gives you the cache's miss rate.
307///
308/// This is used used in the `Cache` type as part of the identification of a
309/// cache event. Each variant here corresponds to a particular
310/// `PERF_COUNT_HW_CACHE_RESULT_...` constant supported by the
311/// [`perf_event_open`][man] system call.
312///
313/// [man]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
314#[derive(Debug, Clone, Copy, Eq, PartialEq)]
315pub enum CacheResult {
316 /// to measure accesses
317 ACCESS = bindings::perf_hw_cache_op_result_id_PERF_COUNT_HW_CACHE_RESULT_ACCESS,
318
319 /// to measure misses
320 MISS = bindings::perf_hw_cache_op_result_id_PERF_COUNT_HW_CACHE_RESULT_MISS,
321}