mirror of
https://github.com/sharkdp/hyperfine.git
synced 2026-10-29 00:28:57 +00:00
92 lines
2.3 KiB
Rust
92 lines
2.3 KiB
Rust
#![cfg(not(windows))]
|
|
|
|
use std::mem;
|
|
|
|
use crate::timer::CPUTimes;
|
|
use crate::util::units::Second;
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
pub struct CPUInterval {
|
|
/// Total amount of time spent executing in user mode
|
|
pub user: Second,
|
|
|
|
/// Total amount of time spent executing in kernel mode
|
|
pub system: Second,
|
|
}
|
|
|
|
pub struct CPUTimer {
|
|
start_cpu: CPUTimes,
|
|
}
|
|
|
|
impl CPUTimer {
|
|
pub fn start() -> Self {
|
|
CPUTimer {
|
|
start_cpu: get_cpu_times(),
|
|
}
|
|
}
|
|
|
|
pub fn stop(&self) -> (Second, Second) {
|
|
let end_cpu = get_cpu_times();
|
|
let cpu_interval = cpu_time_interval(&self.start_cpu, &end_cpu);
|
|
(cpu_interval.user, cpu_interval.system)
|
|
}
|
|
}
|
|
|
|
/// Read CPU execution times ('user' and 'system')
|
|
fn get_cpu_times() -> CPUTimes {
|
|
use libc::{getrusage, rusage, RUSAGE_CHILDREN};
|
|
|
|
let result: rusage = unsafe {
|
|
let mut buf = mem::zeroed();
|
|
let success = getrusage(RUSAGE_CHILDREN, &mut buf);
|
|
assert_eq!(0, success);
|
|
buf
|
|
};
|
|
|
|
const MICROSEC_PER_SEC: i64 = 1000 * 1000;
|
|
|
|
#[allow(clippy::useless_conversion)]
|
|
CPUTimes {
|
|
user_usec: i64::from(result.ru_utime.tv_sec) * MICROSEC_PER_SEC
|
|
+ i64::from(result.ru_utime.tv_usec),
|
|
system_usec: i64::from(result.ru_stime.tv_sec) * MICROSEC_PER_SEC
|
|
+ i64::from(result.ru_stime.tv_usec),
|
|
}
|
|
}
|
|
|
|
/// Compute the time intervals in between two `CPUTimes` snapshots
|
|
fn cpu_time_interval(start: &CPUTimes, end: &CPUTimes) -> CPUInterval {
|
|
CPUInterval {
|
|
user: ((end.user_usec - start.user_usec) as f64) * 1e-6,
|
|
system: ((end.system_usec - start.system_usec) as f64) * 1e-6,
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
use approx::assert_relative_eq;
|
|
|
|
#[test]
|
|
fn test_cpu_time_interval() {
|
|
let t_a = CPUTimes {
|
|
user_usec: 12345,
|
|
system_usec: 54321,
|
|
};
|
|
|
|
let t_b = CPUTimes {
|
|
user_usec: 20000,
|
|
system_usec: 70000,
|
|
};
|
|
|
|
let t_zero = cpu_time_interval(&t_a, &t_a);
|
|
assert!(t_zero.user.abs() < f64::EPSILON);
|
|
assert!(t_zero.system.abs() < f64::EPSILON);
|
|
|
|
let t_ab = cpu_time_interval(&t_a, &t_b);
|
|
assert_relative_eq!(0.007655, t_ab.user);
|
|
assert_relative_eq!(0.015679, t_ab.system);
|
|
|
|
let t_ba = cpu_time_interval(&t_b, &t_a);
|
|
assert_relative_eq!(-0.007655, t_ba.user);
|
|
assert_relative_eq!(-0.015679, t_ba.system);
|
|
}
|