crabscore_analysis/
metrics.rs1use anyhow::Result;
4use crabscore_core::metrics::{
5 LatencyMetrics, PerformanceMetrics, ResourceMetrics, ScalabilityMetrics, ThroughputMetrics,
6};
7use std::time::Instant;
8use tokio::process::Command;
9
10#[derive(Debug, Clone)]
12pub struct BenchmarkOptions {
13 pub warmup: u32,
15 pub iterations: u32,
17 pub args: Vec<String>,
19}
20
21impl Default for BenchmarkOptions {
22 fn default() -> Self {
23 Self {
24 warmup: 1,
25 iterations: 5,
26 args: Vec::new(),
27 }
28 }
29}
30
31#[derive(Default)]
33pub struct BenchmarkRunner {
34 opts: BenchmarkOptions,
35}
36
37impl BenchmarkRunner {
38 pub fn new(opts: BenchmarkOptions) -> Self {
40 Self { opts }
41 }
42
43 pub async fn benchmark<P: AsRef<std::path::Path>>(
45 &self,
46 executable: P,
47 ) -> Result<PerformanceMetrics> {
48 let exe = executable.as_ref();
49 let mut samples = Vec::with_capacity(self.opts.iterations as usize);
50
51 for _ in 0..self.opts.warmup {
53 let _ = Command::new(exe).args(&self.opts.args).status().await?;
54 }
55
56 for _ in 0..self.opts.iterations {
58 let start = Instant::now();
59 let status = Command::new(exe).args(&self.opts.args).status().await?;
60 let elapsed = start.elapsed();
61 if status.success() {
62 samples.push(elapsed.as_secs_f64() * 1000.0); }
64 }
65
66 if samples.is_empty() {
67 return Ok(PerformanceMetrics::default());
68 }
69
70 samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
71 let idx =
72 |p: f64| ((p * (samples.len() as f64 - 1.0)).round() as usize).min(samples.len() - 1);
73
74 let latency = LatencyMetrics {
75 p50_ms: samples[idx(0.50)],
76 p95_ms: samples[idx(0.95)],
77 p99_ms: samples[idx(0.99)],
78 cold_start_ms: samples[0],
79 ttfb_ms: 0.0, };
81
82 let throughput = ThroughputMetrics {
84 requests_per_second: if latency.p50_ms > 0.0 {
85 1000.0 / latency.p50_ms
86 } else {
87 0.0
88 },
89 mb_per_second: 0.0,
90 concurrent_connections: 0,
91 queue_depth: 0.0,
92 };
93
94 let perf = PerformanceMetrics {
95 latency,
96 throughput,
97 resource_usage: ResourceMetrics::default(),
98 scalability: ScalabilityMetrics::default(),
99 };
100
101 Ok(perf)
102 }
103}