diff --git a/Cargo.toml b/Cargo.toml index 069bbd8..7acddaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,5 +20,5 @@ license = "MIT" [workspace.dependencies] harness = { path = "./harness", version = "0.0" } -harness-macros = { path = "./harness/macros", version = "0.0.1" } -harness-probe-perf = { path = "./probes/perf", version = "0.0.4" } +harness-macros = { path = "./harness/macros", version = "0.0.2" } +harness-probe-perf = { path = "./probes/perf", version = "0.0.5" } diff --git a/harness/Cargo.toml b/harness/Cargo.toml index 94a08cc..1b4e31d 100644 --- a/harness/Cargo.toml +++ b/harness/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "harness" -version = "0.0.5" +version = "0.0.6" description = "Precise and reproducible benchmarking" repository = "https://github.com/wenyuzhao/harness" homepage = "https://github.com/wenyuzhao/harness" diff --git a/harness/macros/Cargo.toml b/harness/macros/Cargo.toml index b7ff5b0..3be9f75 100644 --- a/harness/macros/Cargo.toml +++ b/harness/macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "harness-macros" -version = "0.0.1" +version = "0.0.2" description = "Procedural macros for the harness crate" repository = "https://github.com/wenyuzhao/harness" homepage = "https://github.com/wenyuzhao/harness" diff --git a/harness/macros/src/lib.rs b/harness/macros/src/lib.rs index 43a59e3..389b3d4 100644 --- a/harness/macros/src/lib.rs +++ b/harness/macros/src/lib.rs @@ -130,7 +130,7 @@ pub fn probe(_attr: TokenStream, item: TokenStream) -> TokenStream { #input #[no_mangle] - pub extern "C" fn harness_register_probe(probes: &mut ProbeManager) { + pub extern "C" fn harness_register_probe(probes: &mut ::harness::probe::ProbeManager) { probes.register(Box::new(#name::default())); } }; diff --git a/harness/src/bencher.rs b/harness/src/bencher.rs index 55c2ee3..d4b6b84 100644 --- a/harness/src/bencher.rs +++ b/harness/src/bencher.rs @@ -79,7 +79,7 @@ impl<'a> Drop for BenchTimer<'a> { *state = BencherState::AfterTiming; } let elapsed = self.start_time.elapsed(); - self.bencher.timing_end(); + self.bencher.timing_end(elapsed.clone()); let mut lock = self.bencher.elapsed.lock().unwrap(); assert!(lock.is_none(), "More than one benchmark timer detected"); *lock = Some(elapsed); @@ -142,12 +142,13 @@ impl Bencher { ) } - fn timing_end(&self) { + fn timing_end(&self, walltime: Duration) { let mut probes = self.probes.borrow_mut(); probes.end( &self.bench, self.current_iteration, !self.is_timing_iteration(), + walltime, ) } @@ -235,6 +236,17 @@ impl Bencher { .unwrap() .push((name.as_ref().to_owned(), Box::new(value))); } + + /// Returns the wall-clock time of the last timing phase. + /// Returns `None` if the timing phase has not finished yet. + pub fn get_walltime(&self) -> Option { + self.elapsed.lock().unwrap().clone() + } + + /// Returns the value of a counter as a floating point number. + pub fn get_raw_counter_value(&self, name: impl AsRef) -> Option { + self.probes.borrow().get_value(name.as_ref()) + } } pub struct SingleBenchmarkRunner { diff --git a/harness/src/probe.rs b/harness/src/probe.rs index 5c3e194..7c52a2c 100644 --- a/harness/src/probe.rs +++ b/harness/src/probe.rs @@ -7,12 +7,17 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::bencher::{StatPrintFormat, Value}; -#[derive(Default)] struct Counters { counters: Vec<(String, f32)>, } impl Counters { + pub(crate) fn new(walltime: Duration) -> Self { + Self { + counters: vec![("time".to_owned(), walltime.as_micros() as f32 / 1000.0)], + } + } + fn merge(&mut self, values: HashMap) { let mut values = values.iter().collect::>(); values.sort_by_key(|x| x.0.as_str()); @@ -20,6 +25,13 @@ impl Counters { self.counters.push((k.clone(), *v)); } } + + fn get_value(&self, name: &str) -> Option { + self.counters + .iter() + .find(|(k, _)| k == name) + .map(|(_, v)| *v) + } } #[derive(Default, Clone, Debug, Serialize, Deserialize)] @@ -76,7 +88,6 @@ impl Probe for BaseProbe { } pub struct ProbeManager { - base_probe: BaseProbe, probes: Vec>, counters: Counters, libraries: Vec, @@ -85,9 +96,8 @@ pub struct ProbeManager { impl ProbeManager { pub(crate) fn new() -> Self { Self { - base_probe: BaseProbe::default(), probes: vec![], - counters: Counters::default(), + counters: Counters::new(Duration::ZERO), libraries: vec![], } } @@ -122,7 +132,6 @@ impl ProbeManager { } probe_args.push(Some(args)); } - self.base_probe.init(ProbeArgs::default()); for (i, probe) in self.probes.iter_mut().enumerate() { let args = probe_args[i].take().unwrap(); probe.init(args); @@ -130,34 +139,40 @@ impl ProbeManager { } pub(crate) fn deinit(&mut self) { - self.base_probe.deinit(); for probe in self.probes.iter_mut() { probe.deinit(); } } pub(crate) fn begin(&mut self, benchmark: &str, iteration: usize, warmup: bool) { - self.base_probe.begin(benchmark, iteration, warmup); for probe in self.probes.iter_mut() { probe.begin(benchmark, iteration, warmup) } } - pub(crate) fn end(&mut self, benchmark: &str, iteration: usize, warmup: bool) { + pub(crate) fn end( + &mut self, + benchmark: &str, + iteration: usize, + warmup: bool, + walltime: Duration, + ) { // harness_end - self.base_probe.end(benchmark, iteration, warmup); for probe in self.probes.iter_mut() { probe.end(benchmark, iteration, warmup) } // report values - let mut counters = Counters::default(); - counters.merge(self.base_probe.report()); + let mut counters = Counters::new(walltime); for probe in self.probes.iter_mut() { counters.merge(probe.report()); } self.counters = counters; } + pub(crate) fn get_value(&self, name: &str) -> Option { + self.counters.get_value(name) + } + fn dump_counters_stderr_table(&self, stats: &[(String, Box)]) { for (name, _) in stats { eprint!("{}\t", name); diff --git a/probes/perf/Cargo.toml b/probes/perf/Cargo.toml index e56e095..621b8ce 100644 --- a/probes/perf/Cargo.toml +++ b/probes/perf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "harness-probe-perf" -version = "0.0.4" +version = "0.0.5" description = "harness probe for reporting linux perf-event counter values" repository = "https://github.com/wenyuzhao/harness" homepage = "https://github.com/wenyuzhao/harness" diff --git a/probes/perf/src/lib.rs b/probes/perf/src/lib.rs index d99c770..8784489 100644 --- a/probes/perf/src/lib.rs +++ b/probes/perf/src/lib.rs @@ -1,9 +1,9 @@ #[cfg(target_os = "linux")] use std::collections::HashMap; +use harness::probe::Probe; #[cfg(target_os = "linux")] use harness::probe::ProbeArgs; -use harness::probe::{Probe, ProbeManager}; #[harness::probe] #[derive(Default)]