Mechanical auto-fixes: redundant borrows, clone on Copy, or_insert_with, single-char push_str, get(0) → first(), needless borrow, let_and_return. 150 files, no behavior changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
146 lines
3.7 KiB
Rust
146 lines
3.7 KiB
Rust
//! Performance analysis for ML stress testing
|
|
|
|
use anyhow::Result;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::time::{Duration, SystemTime};
|
|
|
|
use super::{PhaseResult, RequirementsCheck, StressTestConfig};
|
|
|
|
/// Latency statistics
|
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
pub struct LatencyStats {
|
|
pub mean: f64,
|
|
pub min: u64,
|
|
pub max: u64,
|
|
pub p50: u64,
|
|
pub p95: u64,
|
|
pub p99: u64,
|
|
pub count: u64,
|
|
}
|
|
|
|
/// Comprehensive stress test report
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct StressTestReport {
|
|
pub config: StressTestConfig,
|
|
pub total_duration: Duration,
|
|
pub phase_results: Vec<PhaseResult>,
|
|
pub total_predictions: u64,
|
|
pub total_errors: u64,
|
|
pub error_rate: f64,
|
|
pub latency_stats: LatencyStats,
|
|
pub requirements_met: RequirementsCheck,
|
|
pub throughput_achieved: f64,
|
|
pub recommendations: Vec<String>,
|
|
}
|
|
|
|
/// Performance analyzer for stress testing
|
|
#[derive(Debug, Clone)]
|
|
pub struct PerformanceAnalyzer {
|
|
start_time: Option<SystemTime>,
|
|
measurements: Vec<PerformanceMeasurement>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct PerformanceMeasurement {
|
|
timestamp: SystemTime,
|
|
metric_name: String,
|
|
value: f64,
|
|
labels: HashMap<String, String>,
|
|
}
|
|
|
|
impl PerformanceAnalyzer {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
start_time: None,
|
|
measurements: Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub async fn start_monitoring(&self) -> Result<()> {
|
|
// Implementation would start background monitoring
|
|
// For now, this is a placeholder
|
|
Ok(())
|
|
}
|
|
|
|
pub fn record_measurement(
|
|
&mut self,
|
|
metric_name: &str,
|
|
value: f64,
|
|
labels: HashMap<String, String>,
|
|
) {
|
|
self.measurements.push(PerformanceMeasurement {
|
|
timestamp: SystemTime::now(),
|
|
metric_name: metric_name.to_owned(),
|
|
value,
|
|
labels,
|
|
});
|
|
}
|
|
|
|
pub fn generate_summary(&self) -> PerformanceSummary {
|
|
let mut latencies = Vec::new();
|
|
let mut errors = 0;
|
|
let mut total_requests = 0;
|
|
|
|
for measurement in &self.measurements {
|
|
match measurement.metric_name.as_str() {
|
|
"latency" => latencies.push(measurement.value as u64),
|
|
"error" => errors += 1,
|
|
"request" => total_requests += 1,
|
|
_ => {},
|
|
}
|
|
}
|
|
|
|
let latency_stats = if latencies.is_empty() {
|
|
LatencyStats::default()
|
|
} else {
|
|
self.calculate_latency_stats(&latencies)
|
|
};
|
|
|
|
let error_rate = if total_requests > 0 {
|
|
errors as f64 / total_requests as f64
|
|
} else {
|
|
0.0
|
|
};
|
|
|
|
PerformanceSummary {
|
|
latency_stats,
|
|
error_rate,
|
|
total_requests: total_requests as u64,
|
|
total_errors: errors as u64,
|
|
}
|
|
}
|
|
|
|
fn calculate_latency_stats(&self, latencies: &[u64]) -> LatencyStats {
|
|
let mut sorted = latencies.to_vec();
|
|
sorted.sort_unstable();
|
|
|
|
let len = sorted.len();
|
|
let mean = sorted.iter().sum::<u64>() as f64 / len as f64;
|
|
|
|
LatencyStats {
|
|
mean,
|
|
min: sorted[0],
|
|
max: sorted[len - 1],
|
|
p50: sorted[len * 50 / 100],
|
|
p95: sorted[len * 95 / 100],
|
|
p99: sorted[len * 99 / 100],
|
|
count: len as u64,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PerformanceSummary {
|
|
pub latency_stats: LatencyStats,
|
|
pub error_rate: f64,
|
|
pub total_requests: u64,
|
|
pub total_errors: u64,
|
|
}
|
|
|
|
impl Default for PerformanceAnalyzer {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|