use std::process::ExitCode;
use std::time::Duration;
use perf_event::events::x86::{Msr, MsrId};
use perf_event::Builder;
fn run() -> std::io::Result<()> {
let tsc_event = Msr::new(MsrId::TSC)?;
let aperf_event = Msr::new(MsrId::APERF)?;
let mperf_event = Msr::new(MsrId::MPERF)?;
let mut tsc = Builder::new(tsc_event)
.one_cpu(0)
.any_pid()
.exclude_hv(false)
.exclude_kernel(false)
.build()?;
let mut aperf = Builder::new(aperf_event)
.one_cpu(0)
.any_pid()
.exclude_hv(false)
.exclude_kernel(false)
.build_with_group(&mut tsc)?;
let mut mperf = Builder::new(mperf_event)
.one_cpu(0)
.any_pid()
.exclude_hv(false)
.exclude_kernel(false)
.build_with_group(&mut tsc)?;
tsc.enable_group()?;
std::thread::sleep(Duration::from_secs(1));
tsc.disable_group()?;
let tsc_val: u64 = tsc.read()?;
let ghz = tsc_val as f64 / (1000000000.0);
let aperf_val = aperf.read()?;
let mperf_val = mperf.read()?;
let ratio = aperf_val as f64 / mperf_val as f64;
let run_freq = ghz * ratio;
println!(
"{tsc_val} ref cycles passed in one second ({ghz:.3} GHz)\n\
APERF: {aperf_val}\n\
MPERF: {mperf_val}\n\
Ratio: {ratio:.4}\n\
Running Frequency: {run_freq:.3} GHz"
);
Ok(())
}
fn main() -> ExitCode {
if let Err(e) = run() {
eprintln!("{e}");
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
}
}