perf_event/
events.rs

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