shumai 0.2.11

A benchmark framework that empowers efficient and correct multi-thread benchmarks.
Documentation
use chrono::{Datelike, Local, Timelike};
use colored::Colorize;
use serde::Serialize;
use serde_json::Value;
use std::{path::PathBuf, str::FromStr, time::Duration};

use crate::{env::RunnerEnv, metrics::Measure, BenchConfig};

#[derive(Debug, Serialize)]
pub struct LoadResults {
    pub time_elapsed: Duration,
    pub user_metrics: Option<Value>,
}

#[derive(Debug, Serialize)]
pub struct ShumaiResult<T: Serialize + Clone + BenchConfig, R: Serialize + Clone> {
    pub config: T,
    #[serde(rename = "load")]
    pub load_results: LoadResults,
    #[serde(rename = "cleanup")]
    pub cleanup_results: Option<Value>,
    pub env: RunnerEnv,
    #[serde(rename = "run")]
    pub bench_results: Vec<ThreadResult<R>>,
}

impl<T: Serialize + Clone + BenchConfig, R: Serialize + Clone> ShumaiResult<T, R> {
    pub(crate) fn new(config: T, load_results: LoadResults, env: RunnerEnv) -> Self {
        Self {
            config,
            load_results,
            cleanup_results: None,
            env,
            bench_results: Vec::new(),
        }
    }

    pub(crate) fn add(&mut self, result: ThreadResult<R>) {
        self.bench_results.push(result);
    }

    pub fn to_json(&self) -> String {
        serde_json::to_string_pretty(self).unwrap()
    }

    pub fn write_json(&self) -> std::io::Result<PathBuf> {
        use std::fs;

        let local_time = Local::now();
        let file = format!(
            "target/benchmark/{}-{:02}-{:02}/{:02}-{:02}-{}.json",
            local_time.year(),
            local_time.month(),
            local_time.day(),
            local_time.hour(),
            local_time.minute(),
            self.config.name()
        );
        let path = PathBuf::from_str(&file).unwrap();
        let json_str = self.to_json();
        if let Some(parent) = path.parent() {
            fs::create_dir_all(parent)?;
        }
        fs::write(&path, json_str)?;
        println!(
            "{}",
            format!("Benchmark results saved to file: {}", file).green()
        );
        Ok(path)
    }
}

#[derive(Debug, Serialize)]
pub struct ThreadResult<R: Serialize> {
    pub thread_cnt: usize,
    pub iterations: Vec<BenchValue<R>>,
}

#[derive(Debug, Clone, Serialize)]
pub struct BenchValue<R: Serialize> {
    pub(crate) result: R,
    pub(crate) measurements: Vec<Measure>,
}