Skip to content

Commit

Permalink
Refactor Value
Browse files Browse the repository at this point in the history
  • Loading branch information
wenyuzhao committed May 17, 2024
1 parent 8cc51be commit 3d985a1
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 48 deletions.
104 changes: 83 additions & 21 deletions harness/src/bencher.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::convert::TryFrom;
use std::fmt;
use std::{
cell::RefCell,
path::PathBuf,
Expand Down Expand Up @@ -44,23 +46,83 @@ pub struct BenchArgs {
pub current_build: Option<String>,
}

pub trait Value: ToString + 'static {}
#[derive(Debug, Clone, Copy)]
pub enum Value {
F64(f64),
F32(f32),
Usize(usize),
Isize(isize),
U64(u64),
I64(i64),
U32(u32),
I32(i32),
U16(u16),
I16(i16),
U8(u8),
I8(i8),
Bool(bool),
}

impl Value {
pub(crate) fn into_string(self) -> String {
match self {
Value::F64(v) => v.to_string(),
Value::F32(v) => v.to_string(),
Value::Usize(v) => v.to_string(),
Value::Isize(v) => v.to_string(),
Value::U64(v) => v.to_string(),
Value::I64(v) => v.to_string(),
Value::U32(v) => v.to_string(),
Value::I32(v) => v.to_string(),
Value::U16(v) => v.to_string(),
Value::I16(v) => v.to_string(),
Value::U8(v) => v.to_string(),
Value::I8(v) => v.to_string(),
Value::Bool(v) => v.to_string(),
}
}
}

macro_rules! impl_helper_traits {
($variant: ident, $t:ty) => {
impl From<$t> for Value {
fn from(v: $t) -> Self {
Value::$variant(v)
}
}

impl Value for f64 {}
impl Value for f32 {}
impl Value for usize {}
impl Value for isize {}
impl Value for u128 {}
impl Value for i128 {}
impl Value for u64 {}
impl Value for i64 {}
impl Value for u32 {}
impl Value for i32 {}
impl Value for u16 {}
impl Value for i16 {}
impl Value for u8 {}
impl Value for i8 {}
impl Value for bool {}
impl TryFrom<Value> for $t {
type Error = ();

fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::$variant(v) => Ok(v),
_ => Err(()),
}
}
}
};
}

impl_helper_traits!(F64, f64);
impl_helper_traits!(F32, f32);
impl_helper_traits!(Usize, usize);
impl_helper_traits!(Isize, isize);
impl_helper_traits!(U64, u64);
impl_helper_traits!(I64, i64);
impl_helper_traits!(U32, u32);
impl_helper_traits!(I32, i32);
impl_helper_traits!(U16, u16);
impl_helper_traits!(I16, i16);
impl_helper_traits!(U8, u8);
impl_helper_traits!(I8, i8);
impl_helper_traits!(Bool, bool);

impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.into_string())
}
}

pub struct BenchTimer<'a> {
start_time: std::time::Instant,
Expand Down Expand Up @@ -96,7 +158,7 @@ pub struct Bencher {
max_iterations: usize,
elapsed: Mutex<Option<Duration>>,
probes: RefCell<ProbeManager>,
extra_stats: Mutex<Vec<(String, Box<dyn Value>)>>,
extra_stats: Mutex<Vec<(String, Value)>>,
state: Mutex<BencherState>,
}

Expand Down Expand Up @@ -226,11 +288,11 @@ impl Bencher {
///
/// Please ensure you are collecting the statistics in a cheap way during the timing phase,
/// and call this function only after the timing phase.
pub fn add_stat(&self, name: impl AsRef<str>, value: impl Value) {
pub fn add_stat(&self, name: impl AsRef<str>, value: impl Into<Value>) {
self.extra_stats
.lock()
.unwrap()
.push((name.as_ref().to_owned(), Box::new(value)));
.push((name.as_ref().to_owned(), value.into()));
}

/// Returns the wall-clock time of the last timing phase.
Expand All @@ -239,8 +301,8 @@ impl Bencher {
*self.elapsed.lock().unwrap()
}

/// Returns the value of a counter as a floating point number.
pub fn get_raw_counter_value(&self, name: impl AsRef<str>) -> Option<f32> {
/// Returns the value of a counter.
pub fn get_raw_counter_value(&self, name: impl AsRef<str>) -> Option<Value> {
self.probes.borrow().get_value(name.as_ref())
}
}
Expand Down
33 changes: 18 additions & 15 deletions harness/src/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,28 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::bencher::Value;

struct Counters {
counters: Vec<(String, f32)>,
counters: Vec<(String, Value)>,
}

impl Counters {
pub(crate) fn new(walltime: Duration) -> Self {
Self {
counters: vec![("time".to_owned(), walltime.as_micros() as f32 / 1000.0)],
counters: vec![(
"time".to_owned(),
(walltime.as_micros() as f32 / 1000.0).into(),
)],
}
}

fn merge(&mut self, values: HashMap<String, f32>) {
fn merge(&mut self, values: HashMap<String, Value>) {
let mut values = values.iter().collect::<Vec<_>>();
values.sort_by_key(|x| x.0.as_str());
for (k, v) in values {
self.counters.push((k.clone(), *v));
}
}

fn get_value(&self, name: &str) -> Option<f32> {
fn get_value(&self, name: &str) -> Option<Value> {
self.counters
.iter()
.find(|(k, _)| k == name)
Expand Down Expand Up @@ -57,7 +60,7 @@ pub trait Probe {

fn end(&mut self, benchmark: &str, iteration: usize, warmup: bool) {}

fn report(&mut self) -> HashMap<String, f32> {
fn report(&mut self) -> HashMap<String, Value> {
HashMap::new()
}

Expand All @@ -79,9 +82,12 @@ impl Probe for BaseProbe {
self.elapsed = self.start.unwrap().elapsed();
}

fn report(&mut self) -> HashMap<String, f32> {
fn report(&mut self) -> HashMap<String, Value> {
let mut values = HashMap::new();
values.insert("time".to_owned(), self.elapsed.as_micros() as f32 / 1000.0);
values.insert(
"time".to_owned(),
(self.elapsed.as_micros() as f32 / 1000.0).into(),
);
values
}
}
Expand Down Expand Up @@ -168,20 +174,17 @@ impl ProbeManager {
self.counters = counters;
}

pub(crate) fn get_value(&self, name: &str) -> Option<f32> {
pub(crate) fn get_value(&self, name: &str) -> Option<Value> {
self.counters.get_value(name)
}

pub(crate) fn get_counter_values(
&self,
extra_stats: Vec<(String, Box<dyn Value>)>,
) -> HashMap<String, Box<dyn Value>> {
pub(crate) fn get_counter_values(&self, extra: Vec<(String, Value)>) -> HashMap<String, Value> {
// Collect all stats
let mut stats_map: HashMap<String, Box<dyn Value>> = HashMap::new();
let mut stats_map: HashMap<String, Value> = HashMap::new();
for (name, value) in &self.counters.counters {
stats_map.insert(name.clone(), Box::new(*value));
stats_map.insert(name.clone(), *value);
}
for (name, value) in extra_stats {
for (name, value) in extra {
stats_map.insert(name.clone(), value);
}
stats_map
Expand Down
18 changes: 9 additions & 9 deletions harness/src/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,28 @@ pub(crate) struct Record<'a> {
pub format: StatPrintFormat,
pub iteration: usize,
pub is_timing_iteration: bool,
pub stats: HashMap<String, Box<dyn Value>>,
pub stats: HashMap<String, Value>,
}

impl<'a> Record<'a> {
fn dump_counters_stderr_table(&self, stats: &[(String, Box<dyn Value>)]) {
fn dump_counters_stderr_table(&self, stats: &[(String, Value)]) {
for (name, _) in stats {
eprint!("{}\t", name);
}
eprintln!();
for (_, value) in stats {
eprint!("{}\t", value.to_string());
eprint!("{}\t", value.into_string());
}
eprintln!();
}

fn dump_counters_stderr_yaml(&self, stats: &[(String, Box<dyn Value>)]) {
fn dump_counters_stderr_yaml(&self, stats: &[(String, Value)]) {
for (name, value) in stats {
eprintln!("{}: {}", name, value.to_string());
eprintln!("{}: {}", name, value.into_string());
}
}

fn dump_counters_stderr(&self, stats: &[(String, Box<dyn Value>)], format: StatPrintFormat) {
fn dump_counters_stderr(&self, stats: &[(String, Value)], format: StatPrintFormat) {
let force_table = std::env::var("HARNESS_LOG_STAT_FORMAT") == Ok("table".to_owned());
if force_table {
return self.dump_counters_stderr_table(stats);
Expand All @@ -52,7 +52,7 @@ impl<'a> Record<'a> {
}
}

fn dump_counters_csv(&self, stats: &[(String, Box<dyn Value>)]) {
fn dump_counters_csv(&self, stats: &[(String, Value)]) {
if let Some(csv) = self.csv {
if !csv.exists() {
let mut headers = "bench,build,invocation,iteration".to_owned();
Expand All @@ -71,7 +71,7 @@ impl<'a> Record<'a> {
self.iteration
);
for (_, value) in stats {
record += &format!(",{}", value.to_string());
record += &format!(",{}", value.into_string());
}
let mut csv = OpenOptions::new().append(true).open(csv).unwrap();
writeln!(csv, "{record}").unwrap();
Expand All @@ -81,7 +81,7 @@ impl<'a> Record<'a> {
pub fn dump_values(mut self) {
let mut stats_map = std::mem::take(&mut self.stats);
let time = stats_map.remove("time");
let mut stats: Vec<(String, Box<dyn Value>)> = vec![];
let mut stats: Vec<(String, Value)> = vec![];
for (name, value) in stats_map {
stats.push((name.clone(), value));
}
Expand Down
6 changes: 3 additions & 3 deletions probes/perf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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, Value};

#[harness::probe]
#[derive(Default)]
Expand Down Expand Up @@ -58,11 +58,11 @@ impl Probe for PerfEventProbe {
}

/// Report data after the timing iteration.
fn report(&mut self) -> HashMap<String, f32> {
fn report(&mut self) -> HashMap<String, Value> {
let mut values = HashMap::new();
for (i, e) in self.events.iter().enumerate() {
let v = e.read().unwrap().value as f32;
values.insert(self.event_names[i].clone(), v);
values.insert(self.event_names[i].clone(), v.into());
}
values
}
Expand Down

0 comments on commit 3d985a1

Please sign in to comment.