Struct Counter

Source
pub struct Counter { /* private fields */ }
Expand description

Event counter.

Linux has many performance events to help developers identify performance issues with their programs. The perf_event_open system call exposes the performance event subsystem for us to monitor these events.

This type is the core of utilizing perf_event_open, which provides the event counting functionality of perf_event_open, similar to the perf stat command.

§Permission

Access to performance monitoring and observability operations needs CAP_PERFMON or CAP_SYS_ADMIN Linux capability, or consider adjusting /proc/sys/kernel/perf_event_paranoid for users without these capabilities.

Possible values:

  • -1: Allow use of (almost) all events by all users. Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK.
  • >= 0: Disallow raw and ftrace function tracepoint access.
  • >= 1: Disallow CPU event access.
  • >= 2: Disallow kernel profiling.

To make the adjusted perf_event_paranoid setting permanent, preserve it in /etc/sysctl.conf (e.g., kernel.perf_event_paranoid = <setting>).

§Examples

use perf_event_open::config::{Cpu, Opts, Proc, SampleOn, Size};
use perf_event_open::count::Counter;
use perf_event_open::event::hw::Hardware;

// Count retired instructions on current process, all CPUs.
let event = Hardware::Instr;
let target = (Proc::CURRENT, Cpu::ALL);

let mut opts = Opts::default();
opts.sample_on = SampleOn::Freq(1000); // 1000 samples per second.
opts.sample_format.user_stack = Some(Size(8)); // Dump 8-bytes user stack in sample.

let counter = Counter::new(event, target, opts).unwrap();

counter.enable().unwrap(); // Start the counter.
fn fib(n: usize) -> usize {
    match n {
        0 => 0,
        1 => 1,
        n => fib(n - 1) + fib(n - 2),
    }
}
std::hint::black_box(fib(30));
counter.disable().unwrap(); // Stop the counter.

let instrs = counter.stat().unwrap().count;
println!("{} instructions retired", instrs);

Implementations§

Source§

impl Counter

Source

pub fn new( event: impl TryInto<Event, Error = Error>, target: impl Into<Target>, opts: impl Borrow<Opts>, ) -> Result<Self>

Creates a new event counter.

Source

pub fn enable_all() -> Result<()>

Enables all counters created by the current process.

Source

pub fn disable_all() -> Result<()>

Disables all counters created by the current process.

Source

pub fn sampler(&self, exp: u8) -> Result<Sampler>

Create a sampler for this counter.

The sampler needs a ring-buffer to store metadata and records, and 1 + 2^exp pages will be allocated for this.

A counter cannot have multiple samplers simultaneously. Attempting to create a new sampler while the previous one is still active will result in ErrorKind::AlreadyExists.

Source

pub fn file(&self) -> &File

Returns the file handle opened by perf_event_open system call for the current event.

This might be useful if we want to interact with the handle directly.

Source

pub fn id(&self) -> Result<u64>

Returns the event ID.

The event ID is a globally incremented ID used to distinguish the results of different counters.

This is the same as Stat::id, SiblingStat::id and RecordId::id.

Source

pub fn enable(&self) -> Result<()>

Enable counter.

Counter will start to accumulate event counts.

Source

pub fn disable(&self) -> Result<()>

Disable counter.

Counter will stop to accumulate event counts.

Source

pub fn clear_count(&self) -> Result<()>

Clear event count.

This will only clear the event counts in the statistics, other fields (such as time_enabled) are not affected.

Source

pub fn stat(&self) -> Result<Stat>

Returns counter statistics.

Source

pub fn attach_bpf(&self, file: &File) -> Result<()>

Attach a BPF program to an existing kprobe tracepoint event.

The argument is a BPF program file that was created by a previous bpf system call.

Source

pub fn query_bpf(&self, len: u32) -> Result<(Vec<u32>, Option<u32>)>

Source

pub fn with_ftrace_filter(&self, filter: &CStr) -> Result<()>

Add an ftrace filter to current event.

Source

pub fn switch_to<E>(&self, event: E) -> Result<()>
where E: TryInto<Event, Error = Error>,

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.