use std::{collections::HashMap, path::PathBuf};
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use crate::utils;
#[derive(Deserialize)]
pub(crate) struct CargoConfig {
package: CargoConfigPackage,
#[serde(default)]
pub(crate) bench: Vec<CargoBenchConfig>,
#[serde(flatten)]
_others: HashMap<String, toml::Value>,
}
impl CargoConfig {
pub fn load_cargo_toml() -> anyhow::Result<CargoConfig> {
if !PathBuf::from("./Cargo.toml").is_file() {
anyhow::bail!("Failed to load ./Cargo.toml");
}
let s = std::fs::read_to_string("./Cargo.toml")?;
Ok(toml::from_str::<CargoConfig>(&s)?)
}
}
#[derive(Deserialize)]
struct CargoConfigPackage {
metadata: Option<CargoConfigPackageMetadata>,
#[serde(flatten)]
_others: HashMap<String, toml::Value>,
}
#[derive(Deserialize)]
pub(crate) struct CargoBenchConfig {
pub(crate) name: String,
#[serde(default)]
pub(crate) harness: bool,
#[serde(flatten)]
_others: HashMap<String, toml::Value>,
}
#[derive(Deserialize)]
struct CargoConfigPackageMetadata {
harness: Option<HarnessConfig>,
#[serde(flatten)]
_others: HashMap<String, toml::Value>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct HarnessConfig {
pub profiles: HashMap<String, Profile>,
}
impl HarnessConfig {
pub fn load_from_cargo_toml() -> anyhow::Result<HarnessConfig> {
if !PathBuf::from("./Cargo.toml").is_file() {
anyhow::bail!("Failed to load ./Cargo.toml");
}
let s = std::fs::read_to_string("./Cargo.toml")?;
let mut harness = toml::from_str::<CargoConfig>(&s)?
.package
.metadata
.and_then(|m| m.harness)
.unwrap_or_default();
if harness.profiles.is_empty() {
harness
.profiles
.insert("default".to_owned(), Default::default());
}
Ok(harness)
}
}
impl Default for HarnessConfig {
fn default() -> Self {
Self {
profiles: [("default".to_owned(), Default::default())]
.into_iter()
.collect(),
}
}
}
fn default_iterations() -> usize {
5
}
fn default_invocations() -> usize {
10
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Profile {
#[serde(default)]
pub probes: Vec<String>,
#[serde(default)]
pub env: HashMap<String, String>,
#[serde(default)]
pub builds: HashMap<String, BuildConfig>,
#[serde(default = "default_iterations")]
pub iterations: usize,
#[serde(default = "default_invocations")]
pub invocations: usize,
pub baseline: Option<String>,
}
impl Default for Profile {
fn default() -> Self {
Self {
probes: Vec::new(),
env: HashMap::new(),
builds: HashMap::new(),
iterations: default_iterations(),
invocations: default_invocations(),
baseline: None,
}
}
}
fn default_true() -> bool {
true
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct BuildConfig {
#[serde(default)]
pub features: Vec<String>,
#[serde(default = "default_true", rename = "default-features")]
pub default_features: bool,
#[serde(default)]
pub env: HashMap<String, String>,
#[serde(default)]
pub commit: Option<String>,
}
impl Default for BuildConfig {
fn default() -> Self {
Self {
features: Vec::new(),
default_features: true,
env: HashMap::new(),
commit: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CrateInfo {
pub name: String,
pub target_dir: PathBuf,
pub benches: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RunInfo {
pub runid: String,
#[serde(rename = "start-time-utc")]
pub start_timestamp_utc: i64,
#[serde(rename = "finish-time-utc")]
pub finish_timestamp_utc: Option<i64>,
pub commit: String,
#[serde(rename = "crate")]
pub crate_info: CrateInfo,
pub profile: Profile,
pub system: SystemInfo,
}
impl RunInfo {
pub fn new(
crate_info: CrateInfo,
profile: Profile,
runid: String,
start_time: DateTime<Local>,
) -> anyhow::Result<Self> {
Ok(Self {
crate_info,
system: utils::sys::get_current_system_info(),
profile,
runid,
commit: utils::git::get_git_hash()?,
start_timestamp_utc: start_time.to_utc().timestamp(),
finish_timestamp_utc: None,
})
}
pub fn load(path: &PathBuf) -> anyhow::Result<Self> {
let content = std::fs::read_to_string(path)?;
Ok(toml::from_str(&content)?)
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SystemInfo {
pub host: String,
pub os: String,
pub arch: String,
#[serde(rename = "kernel-version")]
pub kernel: String,
#[serde(rename = "cpu-model")]
pub cpu_model: String,
#[serde(rename = "cpu-frequency")]
pub cpu_frequency: Vec<usize>,
pub memory_size: usize,
pub swap_size: usize,
#[cfg(target_os = "linux")]
pub users: Vec<String>,
pub processes: usize,
pub env: HashMap<String, String>,
pub pid: usize,
pub rustc: String,
#[cfg(target_os = "linux")]
#[serde(rename = "scaling-governor")]
pub scaling_governor: Vec<String>,
}