#[derive(Debug, Clone, Default)]
pub struct FrameProfile {
pub cycle: u32,
pub duration_ms: u64,
pub memory_bytes: usize,
pub tests_passed: u32,
pub tests_failed: u32,
pub input_seed: u64,
pub input_size: usize,
}
#[derive(Debug, Clone, Default)]
pub struct StressReport {
pub frames: Vec<FrameProfile>,
pub cycles_completed: u32,
pub total_passed: u32,
pub total_failed: u32,
pub anomalies: Vec<Anomaly>,
}
impl StressReport {
#[must_use]
pub fn mean_frame_time_ms(&self) -> f64 {
if self.frames.is_empty() {
return 0.0;
}
let sum: u64 = self.frames.iter().map(|f| f.duration_ms).sum();
sum as f64 / self.frames.len() as f64
}
#[must_use]
pub fn timing_variance(&self) -> f64 {
if self.frames.len() < 2 {
return 0.0;
}
let mean = self.mean_frame_time_ms();
if mean == 0.0 {
return 0.0;
}
let variance: f64 = self
.frames
.iter()
.map(|f| {
let diff = f.duration_ms as f64 - mean;
diff * diff
})
.sum::<f64>()
/ self.frames.len() as f64;
variance.sqrt() / mean
}
#[must_use]
pub fn max_frame_time_ms(&self) -> u64 {
self.frames.iter().map(|f| f.duration_ms).max().unwrap_or(0)
}
#[must_use]
pub fn pass_rate(&self) -> f64 {
let total = self.total_passed + self.total_failed;
if total == 0 {
return 1.0;
}
self.total_passed as f64 / total as f64
}
pub fn add_frame(&mut self, profile: FrameProfile) {
self.total_passed += profile.tests_passed;
self.total_failed += profile.tests_failed;
self.cycles_completed += 1;
self.frames.push(profile);
}
}
#[derive(Debug, Clone)]
pub struct Anomaly {
pub cycle: u32,
pub kind: AnomalyKind,
pub description: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AnomalyKind {
SlowFrame,
HighMemory,
TestFailure,
TimingSpike,
NonDeterministic,
}
#[derive(Debug, Clone)]
pub struct PerformanceThresholds {
pub max_frame_time_ms: u64,
pub max_memory_bytes: usize,
pub max_timing_variance: f64,
pub max_failure_rate: f64,
}
impl Default for PerformanceThresholds {
fn default() -> Self {
Self {
max_frame_time_ms: 100, max_memory_bytes: 64 * 1024 * 1024, max_timing_variance: 0.2, max_failure_rate: 0.01, }
}
}
#[derive(Debug, Clone)]
pub struct PerformanceResult {
pub passed: bool,
pub max_frame_ms: u64,
pub mean_frame_ms: f64,
pub variance: f64,
pub pass_rate: f64,
pub violations: Vec<String>,
}
#[must_use]
pub fn verify_performance(
report: &StressReport,
thresholds: &PerformanceThresholds,
) -> PerformanceResult {
let max_frame = report.max_frame_time_ms();
let mean_frame = report.mean_frame_time_ms();
let variance = report.timing_variance();
let pass_rate = report.pass_rate();
let mut violations = Vec::new();
if max_frame > thresholds.max_frame_time_ms {
violations.push(format!(
"Max frame time {}ms exceeds threshold {}ms",
max_frame, thresholds.max_frame_time_ms
));
}
if variance > thresholds.max_timing_variance {
violations.push(format!(
"Timing variance {:.3} exceeds threshold {:.3}",
variance, thresholds.max_timing_variance
));
}
if pass_rate < (1.0 - thresholds.max_failure_rate) {
violations.push(format!(
"Pass rate {:.1}% below threshold {:.1}%",
pass_rate * 100.0,
(1.0 - thresholds.max_failure_rate) * 100.0
));
}
PerformanceResult {
passed: violations.is_empty(),
max_frame_ms: max_frame,
mean_frame_ms: mean_frame,
variance,
pass_rate,
violations,
}
}