use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use super::{MetricType, Runtime};
use std::time::Duration;
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BenchmarkConfig {
pub iterations: u32,
pub warmup_iterations: u32,
pub timeout: Duration,
pub output_format: OutputFormat,
pub enable_profiling: bool,
pub workers: u32,
pub output_dir: PathBuf,
pub verbosity: Verbosity,
pub enable_logging: bool,
pub log_file: Option<PathBuf>,
pub name: String,
pub description: Option<String>,
pub tags: Vec<String>,
pub category: Option<String>,
}
impl Default for BenchmarkConfig {
fn default() -> Self {
Self {
iterations: 10,
warmup_iterations: 3,
timeout: Duration::from_secs(60),
output_format: OutputFormat::Json,
enable_profiling: false,
workers: num_cpus::get() as u32,
output_dir: PathBuf::from("benchmark_results"),
verbosity: Verbosity::Info,
enable_logging: false,
log_file: None,
name: "default".to_string(),
description: None,
tags: Vec::new(),
category: None,
}
}
}
impl BenchmarkConfig {
pub fn new() -> Self {
Self::default()
}
pub fn iterations(mut self, iterations: u32) -> Self {
self.iterations = iterations;
self
}
pub fn warmup_iterations(mut self, warmup_iterations: u32) -> Self {
self.warmup_iterations = warmup_iterations;
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}
pub fn output_format(mut self, output_format: OutputFormat) -> Self {
self.output_format = output_format;
self
}
pub fn enable_profiling(mut self, enable: bool) -> Self {
self.enable_profiling = enable;
self
}
pub fn workers(mut self, workers: u32) -> Self {
self.workers = workers;
self
}
pub fn output_dir(mut self, output_dir: PathBuf) -> Self {
self.output_dir = output_dir;
self
}
pub fn verbosity(mut self, verbosity: Verbosity) -> Self {
self.verbosity = verbosity;
self
}
pub fn name(mut self, name: &str) -> Self {
self.name = name.to_string();
self
}
pub fn description(mut self, description: &str) -> Self {
self.description = Some(description.to_string());
self
}
pub fn add_tag(mut self, tag: &str) -> Self {
self.tags.push(tag.to_string());
self
}
pub fn category(mut self, category: &str) -> Self {
self.category = Some(category.to_string());
self
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum OutputFormat {
Json,
Csv,
Html,
Text,
Prometheus,
}
impl Default for OutputFormat {
fn default() -> Self {
OutputFormat::Json
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum Verbosity {
Quiet,
Error,
Warn,
Info,
Debug,
Trace,
}
impl Default for Verbosity {
fn default() -> Self {
Verbosity::Info
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestSuite {
pub name: String,
pub description: String,
pub config: BenchmarkConfig,
pub benchmarks: Vec<BenchmarkTest>,
pub workloads: Vec<WorkloadProfile>,
pub runtimes: Vec<Runtime>,
pub dependencies: Vec<String>,
pub environment: HashMap<String, String>,
pub setup_script: Option<PathBuf>,
pub cleanup_script: Option<PathBuf>,
}
impl TestSuite {
pub fn new(name: &str, description: &str) -> Self {
Self {
name: name.to_string(),
description: description.to_string(),
config: BenchmarkConfig::default(),
benchmarks: Vec::new(),
workloads: Vec::new(),
runtimes: vec![Runtime::Amber],
dependencies: Vec::new(),
environment: HashMap::new(),
setup_script: None,
cleanup_script: None,
}
}
pub fn add_benchmark(mut self, benchmark: BenchmarkTest) -> Self {
self.benchmarks.push(benchmark);
self
}
pub fn add_workload(mut self, workload: WorkloadProfile) -> Self {
self.workloads.push(workload);
self
}
pub fn add_runtime(mut self, runtime: Runtime) -> Self {
self.runtimes.push(runtime);
self
}
pub fn add_env(mut self, key: &str, value: &str) -> Self {
self.environment.insert(key.to_string(), value.to_string());
self
}
pub fn environment(mut self, environment: HashMap<String, String>) -> Self {
self.environment = environment;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BenchmarkTest {
pub name: String,
pub description: String,
pub code: String,
pub language: TestLanguage,
pub expected_result: Option<String>,
pub iterations: Option<u32>,
pub timeout: Option<Duration>,
pub tags: Vec<String>,
pub category: Option<String>,
pub enabled: bool,
pub dependencies: Vec<String>,
pub environment: HashMap<String, String>,
pub setup_code: Option<String>,
pub cleanup_code: Option<String>,
}
impl BenchmarkTest {
pub fn new(name: &str, description: &str, code: &str, language: TestLanguage) -> Self {
Self {
name: name.to_string(),
description: description.to_string(),
code: code.to_string(),
language,
expected_result: None,
iterations: None,
timeout: None,
tags: Vec::new(),
category: None,
enabled: true,
dependencies: Vec::new(),
environment: HashMap::new(),
setup_code: None,
cleanup_code: None,
}
}
pub fn expected_result(mut self, result: &str) -> Self {
self.expected_result = Some(result.to_string());
self
}
pub fn iterations(mut self, iterations: u32) -> Self {
self.iterations = Some(iterations);
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
pub fn add_tag(mut self, tag: &str) -> Self {
self.tags.push(tag.to_string());
self
}
pub fn category(mut self, category: &str) -> Self {
self.category = Some(category.to_string());
self
}
pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
pub fn add_dependency(mut self, dependency: &str) -> Self {
self.dependencies.push(dependency.to_string());
self
}
pub fn add_env(mut self, key: &str, value: &str) -> Self {
self.environment.insert(key.to_string(), value.to_string());
self
}
pub fn environment(mut self, environment: HashMap<String, String>) -> Self {
self.environment = environment;
self
}
pub fn setup_code(mut self, code: &str) -> Self {
self.setup_code = Some(code.to_string());
self
}
pub fn cleanup_code(mut self, code: &str) -> Self {
self.cleanup_code = Some(code.to_string());
self
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum TestLanguage {
JavaScript,
TypeScript,
Python,
Rust,
}
impl Default for TestLanguage {
fn default() -> Self {
TestLanguage::JavaScript
}
}
impl std::fmt::Display for TestLanguage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TestLanguage::JavaScript => write!(f, "javascript"),
TestLanguage::TypeScript => write!(f, "typescript"),
TestLanguage::Python => write!(f, "python"),
TestLanguage::Rust => write!(f, "rust"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkloadProfile {
pub name: String,
pub workload_type: WorkloadType,
pub description: String,
pub parameters: HashMap<String, serde_json::Value>>,
pub resource_requirements: ResourceRequirements,
pub duration: Option<Duration>,
pub iterations: Option<u32>,
pub concurrency: u32,
pub tags: Vec<String>,
pub category: Option<String>,
pub enabled: bool,
}
impl WorkloadProfile {
pub fn new(name: &str, workload_type: WorkloadType, description: &str) -> Self {
Self {
name: name.to_string(),
workload_type,
description: description.to_string(),
parameters: HashMap::new(),
resource_requirements: ResourceRequirements::default(),
duration: None,
iterations: None,
concurrency: 1,
tags: Vec::new(),
category: None,
enabled: true,
}
}
pub fn add_parameter(mut self, key: &str, value: serde_json::Value) -> Self {
self.parameters.insert(key.to_string(), value);
self
}
pub fn parameters(mut self, parameters: HashMap<String, serde_json::Value>) -> Self {
self.parameters = parameters;
self
}
pub fn resource_requirements(mut self, requirements: ResourceRequirements) -> Self {
self.resource_requirements = requirements;
self
}
pub fn duration(mut self, duration: Duration) -> Self {
self.duration = Some(duration);
self
}
pub fn iterations(mut self, iterations: u32) -> Self {
self.iterations = Some(iterations);
self
}
pub fn concurrency(mut self, concurrency: u32) -> Self {
self.concurrency = concurrency;
self
}
pub fn add_tag(mut self, tag: &str) -> Self {
self.tags.push(tag.to_string());
self
}
pub fn category(mut self, category: &str) -> Self {
self.category = Some(category.to_string());
self
}
pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum WorkloadType {
ComputeIntensive,
IoIntensive,
MemoryIntensive,
Concurrent,
AiWorkload,
Mixed,
}
impl std::fmt::Display for WorkloadType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
WorkloadType::ComputeIntensive => write!(f, "compute_intensive"),
WorkloadType::IoIntensive => write!(f, "io_intensive"),
WorkloadType::MemoryIntensive => write!(f, "memory_intensive"),
WorkloadType::Concurrent => write!(f, "concurrent"),
WorkloadType::AiWorkload => write!(f, "ai_workload"),
WorkloadType::Mixed => write!(f, "mixed"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceRequirements {
pub min_memory: Option<u64>,
pub max_memory: Option<u64>,
pub cpu_cores: Option<u32>,
pub network_bandwidth: Option<u64>,
pub disk_io: Option<u64>,
pub gpu_requirements: Option<GpuRequirements>,
}
impl Default for ResourceRequirements {
fn default() -> Self {
Self {
min_memory: None,
max_memory: None,
cpu_cores: None,
network_bandwidth: None,
disk_io: None,
gpu_requirements: None,
}
}
}
impl ResourceRequirements {
pub fn new() -> Self {
Self::default()
}
pub fn min_memory(mut self, memory: u64) -> Self {
self.min_memory = Some(memory);
self
}
pub fn max_memory(mut self, memory: u64) -> Self {
self.max_memory = Some(memory);
self
}
pub fn cpu_cores(mut self, cores: u32) -> Self {
self.cpu_cores = Some(cores);
self
}
pub fn network_bandwidth(mut self, bandwidth: u64) -> Self {
self.network_bandwidth = Some(bandwidth);
self
}
pub fn disk_io(mut self, io: u64) -> Self {
self.disk_io = Some(io);
self
}
pub fn gpu_requirements(mut self, requirements: GpuRequirements) -> Self {
self.gpu_requirements = Some(requirements);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GpuRequirements {
pub min_vram: Option<u64>,
pub compute_capability: Option<u32>,
pub gpu_count: Option<u32>,
}
impl GpuRequirements {
pub fn new() -> Self {
Self {
min_vram: None,
compute_capability: None,
gpu_count: None,
}
}
pub fn min_vram(mut self, vram: u64) -> Self {
self.min_vram = Some(vram);
self
}
pub fn compute_capability(mut self, capability: u32) -> Self {
self.compute_capability = Some(capability);
self
}
pub fn gpu_count(mut self, count: u32) -> Self {
self.gpu_count = Some(count);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeComparison {
pub name: String,
pub description: String,
pub baseline_runtime: Runtime,
pub comparison_runtimes: Vec<Runtime>,
pub benchmarks: Vec<String>,
pub workloads: Vec<String>,
pub comparison_mode: ComparisonMode,
pub significance_level: f64,
pub min_samples: u32,
pub auto_detect_runtimes: bool,
pub generate_report: bool,
pub report_format: OutputFormat,
pub save_history: bool,
pub history_path: Option<PathBuf>,
}
impl Default for RuntimeComparison {
fn default() -> Self {
Self {
name: "default_comparison".to_string(),
description: "Default runtime comparison".to_string(),
baseline_runtime: Runtime::Amber,
comparison_runtimes: vec![Runtime::NodeJs, Runtime::Bun],
benchmarks: Vec::new(),
workloads: Vec::new(),
comparison_mode: ComparisonMode::Statistical,
significance_level: 0.05,
min_samples: 10,
auto_detect_runtimes: true,
generate_report: true,
report_format: OutputFormat::Html,
save_history: true,
history_path: Some(PathBuf::from("benchmark_history")),
}
}
}
impl RuntimeComparison {
pub fn new(name: &str, description: &str) -> Self {
Self {
name: name.to_string(),
description: description.to_string(),
..Self::default()
}
}
pub fn baseline_runtime(mut self, runtime: Runtime) -> Self {
self.baseline_runtime = runtime;
self
}
pub fn add_comparison_runtime(mut self, runtime: Runtime) -> Self {
self.comparison_runtimes.push(runtime);
self
}
pub fn add_benchmark(mut self, benchmark: &str) -> Self {
self.benchmarks.push(benchmark.to_string());
self
}
pub fn add_workload(mut self, workload: &str) -> Self {
self.workloads.push(workload.to_string());
self
}
pub fn comparison_mode(mut self, mode: ComparisonMode) -> Self {
self.comparison_mode = mode;
self
}
pub fn significance_level(mut self, level: f64) -> Self {
self.significance_level = level;
self
}
pub fn min_samples(mut self, samples: u32) -> Self {
self.min_samples = samples;
self
}
pub fn auto_detect_runtimes(mut self, auto_detect: bool) -> Self {
self.auto_detect_runtimes = auto_detect;
self
}
pub fn generate_report(mut self, generate: bool) -> Self {
self.generate_report = generate;
self
}
pub fn report_format(mut self, format: OutputFormat) -> Self {
self.report_format = format;
self
}
pub fn save_history(mut self, save: bool) -> Self {
self.save_history = save;
self
}
pub fn history_path(mut self, path: PathBuf) -> Self {
self.history_path = Some(path);
self
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum ComparisonMode {
Statistical,
Absolute,
Relative,
Percentage,
}
impl Default for ComparisonMode {
fn default() -> Self {
ComparisonMode::Statistical
}
}