Skip to main content

Counter

Struct Counter 

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

A counter for one kind of kernel or hardware event.

A Counter represents a single performance monitoring counter. You select what sort of event you’d like to count when the Counter is created, then you can enable and disable the counter, call its read method to retrieve the current count, and reset it to zero.

A Counter’s value is always a u64.

For example, this counts the number of instructions retired (completed) during a call to println!.

use perf_event::Builder;

fn main() -> std::io::Result<()> {
    let mut counter = Builder::new().build()?;

    let vec = (0..=51).collect::<Vec<_>>();

    counter.enable()?;
    println!("{:?}", vec);
    counter.disable()?;

    println!("{} instructions retired", counter.read()?);

    Ok(())
}

It is often useful to count several different quantities over the same period of time. For example, if you want to measure the average number of clock cycles used per instruction, you must count both clock cycles and instructions retired, for the same range of execution. The [Group] type lets you enable, disable, read, and reset any number of counters simultaneously.

When a counter is dropped, its kernel resources are freed along with it.

Internally, a Counter is just a wrapper around an event file descriptor.

Implementations§

Source§

impl Counter

Source

pub fn id(&self) -> u64

Return this counter’s kernel-assigned unique id.

This can be useful when iterating over Counts.

Source

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

Allow this Counter to begin counting its designated event.

This does not affect whatever value the Counter had previously; new events add to the current count. To clear a Counter, use the reset method.

Note that Group also has an enable method, which enables all its member Counters as a single atomic operation.

Examples found in repository?
examples/println.rs (line 8)
3fn main() -> std::io::Result<()> {
4    let mut counter = Builder::new().build()?;
5
6    let vec = (0..=51).collect::<Vec<_>>();
7
8    counter.enable()?;
9    println!("{:?}", vec);
10    counter.disable()?;
11
12    println!("{} instructions retired", counter.read()?);
13
14    Ok(())
15}
More examples
Hide additional examples
examples/insns-for-pid.rs (line 20)
7fn main() -> std::io::Result<()> {
8    let pid: pid_t = std::env::args()
9        .nth(1)
10        .expect("Usage: insns-for-pid PID")
11        .parse()
12        .expect("Usage: insns-for-pid PID");
13
14    let mut insns = Builder::new()
15        .observe_pid(pid)
16        .kind(Hardware::BRANCH_INSTRUCTIONS)
17        .build()?;
18
19    // Count instructions in PID for five seconds.
20    insns.enable()?;
21    sleep(Duration::from_secs(5));
22    insns.disable()?;
23
24    println!("instructions in last five seconds: {}", insns.read()?);
25
26    Ok(())
27}
Source

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

Make this Counter stop counting its designated event. Its count is unaffected.

Note that Group also has a disable method, which disables all its member Counters as a single atomic operation.

Examples found in repository?
examples/println.rs (line 10)
3fn main() -> std::io::Result<()> {
4    let mut counter = Builder::new().build()?;
5
6    let vec = (0..=51).collect::<Vec<_>>();
7
8    counter.enable()?;
9    println!("{:?}", vec);
10    counter.disable()?;
11
12    println!("{} instructions retired", counter.read()?);
13
14    Ok(())
15}
More examples
Hide additional examples
examples/insns-for-pid.rs (line 22)
7fn main() -> std::io::Result<()> {
8    let pid: pid_t = std::env::args()
9        .nth(1)
10        .expect("Usage: insns-for-pid PID")
11        .parse()
12        .expect("Usage: insns-for-pid PID");
13
14    let mut insns = Builder::new()
15        .observe_pid(pid)
16        .kind(Hardware::BRANCH_INSTRUCTIONS)
17        .build()?;
18
19    // Count instructions in PID for five seconds.
20    insns.enable()?;
21    sleep(Duration::from_secs(5));
22    insns.disable()?;
23
24    println!("instructions in last five seconds: {}", insns.read()?);
25
26    Ok(())
27}
Source

pub fn reset(&mut self) -> Result<()>

Reset the value of this Counter to zero.

Note that Group also has a reset method, which resets all its member Counters as a single atomic operation.

Source

pub fn read(&mut self) -> Result<u64>

Return this Counter’s current value as a u64.

Consider using the read_count_and_time method instead of this one. Some counters are implemented in hardware, and the processor can support only a certain number running at a time. If more counters are requested than the hardware can support, the kernel timeshares them on the hardware. This method gives you no indication whether this has happened; read_count_and_time does.

Note that Group also has a read method, which reads all its member Counters’ values at once.

Examples found in repository?
examples/println.rs (line 12)
3fn main() -> std::io::Result<()> {
4    let mut counter = Builder::new().build()?;
5
6    let vec = (0..=51).collect::<Vec<_>>();
7
8    counter.enable()?;
9    println!("{:?}", vec);
10    counter.disable()?;
11
12    println!("{} instructions retired", counter.read()?);
13
14    Ok(())
15}
More examples
Hide additional examples
examples/insns-for-pid.rs (line 24)
7fn main() -> std::io::Result<()> {
8    let pid: pid_t = std::env::args()
9        .nth(1)
10        .expect("Usage: insns-for-pid PID")
11        .parse()
12        .expect("Usage: insns-for-pid PID");
13
14    let mut insns = Builder::new()
15        .observe_pid(pid)
16        .kind(Hardware::BRANCH_INSTRUCTIONS)
17        .build()?;
18
19    // Count instructions in PID for five seconds.
20    insns.enable()?;
21    sleep(Duration::from_secs(5));
22    insns.disable()?;
23
24    println!("instructions in last five seconds: {}", insns.read()?);
25
26    Ok(())
27}
Source

pub fn read_count_and_time(&mut self) -> Result<CountAndTime>

Return this Counter’s current value and timesharing data.

Some counters are implemented in hardware, and the processor can run only a fixed number of them at a time. If more counters are requested than the hardware can support, the kernel timeshares them on the hardware.

This method returns a CountAndTime struct, whose count field holds the counter’s value, and whose time_enabled and time_running fields indicate how long you had enabled the counter, and how long the counter was actually scheduled on the processor. This lets you detect whether the counter was timeshared, and adjust your use accordingly. Times are reported in nanoseconds.

let cat = counter.read_count_and_time()?;
if cat.time_running == 0 {
    println!("No data collected.");
} else if cat.time_running < cat.time_enabled {
    // Note: this way of scaling is accurate, but `u128` division
    // is usually implemented in software, which may be slow.
    println!("{} instructions (estimated)",
             (cat.count as u128 *
              cat.time_enabled as u128 / cat.time_running as u128) as u64);
} else {
    println!("{} instructions", cat.count);
}

Note that Group also has a read method, which reads all its member Counters’ values at once.

Trait Implementations§

Source§

impl AsRawFd for Counter

Source§

fn as_raw_fd(&self) -> RawFd

Extracts the raw file descriptor. Read more
Source§

impl Debug for Counter

Source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Index<&Counter> for Counts

Source§

type Output = u64

The returned type after indexing.
Source§

fn index(&self, index: &Counter) -> &u64

Performs the indexing (container[index]) operation. Read more
Source§

impl IntoRawFd for Counter

Source§

fn into_raw_fd(self) -> RawFd

Consumes this object, returning the raw underlying file descriptor. Read more

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.