Skip to main content

optirs_bench/regression_tester/
types.rs

1// Core data types and structures for regression testing
2//
3// This module provides all the data structures used throughout the regression testing
4// framework, including performance metrics, analysis results, and statistical types.
5
6use crate::error::Result;
7use crate::regression_tester::config::TestEnvironment;
8use scirs2_core::numeric::Float;
9use serde::{Deserialize, Serialize};
10use std::collections::{HashMap, VecDeque};
11use std::fmt::Debug;
12
13/// Performance metrics for regression testing
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct PerformanceMetrics<A: Float> {
16    /// Execution time metrics
17    pub timing: TimingMetrics,
18    /// Memory usage metrics
19    pub memory: MemoryMetrics,
20    /// Computational efficiency metrics
21    pub efficiency: EfficiencyMetrics<A>,
22    /// Convergence metrics
23    pub convergence: ConvergenceMetrics<A>,
24    /// Custom metrics
25    pub custom: HashMap<String, f64>,
26}
27
28/// Timing metrics
29#[derive(Debug, Clone, Serialize, Deserialize, Default)]
30pub struct TimingMetrics {
31    /// Mean execution time (nanoseconds)
32    pub mean_time_ns: u64,
33    /// Standard deviation of execution time
34    pub std_time_ns: u64,
35    /// Median execution time
36    pub median_time_ns: u64,
37    /// 95th percentile execution time
38    pub p95_time_ns: u64,
39    /// 99th percentile execution time
40    pub p99_time_ns: u64,
41    /// Minimum execution time
42    pub min_time_ns: u64,
43    /// Maximum execution time
44    pub max_time_ns: u64,
45}
46
47/// Memory metrics
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct MemoryMetrics {
50    /// Peak memory usage (bytes)
51    pub peak_memory_bytes: usize,
52    /// Average memory usage (bytes)
53    pub avg_memory_bytes: usize,
54    /// Memory allocation count
55    pub allocation_count: usize,
56    /// Memory fragmentation ratio
57    pub fragmentation_ratio: f64,
58    /// Memory efficiency score
59    pub efficiency_score: f64,
60}
61
62/// Efficiency metrics
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct EfficiencyMetrics<A: Float> {
65    /// FLOPS achieved
66    pub flops: f64,
67    /// Arithmetic intensity
68    pub arithmetic_intensity: f64,
69    /// Cache hit ratio
70    pub cache_hit_ratio: f64,
71    /// CPU utilization
72    pub cpu_utilization: f64,
73    /// Overall efficiency score
74    pub efficiency_score: f64,
75    /// Custom efficiency metrics
76    pub custom_metrics: HashMap<String, A>,
77}
78
79/// Convergence metrics
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct ConvergenceMetrics<A: Float> {
82    /// Final objective value
83    pub final_objective: A,
84    /// Convergence rate
85    pub convergence_rate: f64,
86    /// Iterations to convergence
87    pub iterations_to_convergence: Option<usize>,
88    /// Convergence quality score
89    pub quality_score: f64,
90    /// Stability metrics
91    pub stability_score: f64,
92}
93
94/// Individual performance record
95#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct PerformanceRecord<A: Float> {
97    /// Timestamp of the record
98    pub timestamp: u64,
99    /// Git commit hash (if available)
100    pub commit_hash: Option<String>,
101    /// Branch name
102    pub branch: Option<String>,
103    /// Test environment information
104    pub environment: TestEnvironment,
105    /// Performance metrics
106    pub metrics: PerformanceMetrics<A>,
107    /// Additional metadata
108    pub metadata: HashMap<String, String>,
109}
110
111/// Database metadata
112#[derive(Debug, Serialize, Deserialize)]
113pub struct DatabaseMetadata {
114    /// Database version
115    pub version: String,
116    /// Creation timestamp
117    pub created_at: u64,
118    /// Last update timestamp
119    pub last_updated: u64,
120    /// Total number of records
121    pub total_records: usize,
122}
123
124/// Performance baseline for comparison
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct PerformanceBaseline<A: Float> {
127    /// Baseline name/identifier
128    pub name: String,
129    /// Statistical summary of baseline performance
130    pub baseline_stats: BaselineStatistics<A>,
131    /// Confidence intervals
132    pub confidence_intervals: ConfidenceIntervals,
133    /// Sample count used for baseline
134    pub sample_count: usize,
135    /// Baseline creation timestamp
136    pub created_at: u64,
137    /// Last update timestamp
138    pub updated_at: u64,
139}
140
141/// Statistical summary of baseline performance
142#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct BaselineStatistics<A: Float> {
144    /// Timing statistics
145    pub timing: TimingStatistics,
146    /// Memory statistics
147    pub memory: MemoryStatistics,
148    /// Efficiency statistics
149    pub efficiency: EfficiencyStatistics<A>,
150    /// Convergence statistics
151    pub convergence: ConvergenceStatistics<A>,
152}
153
154/// Timing statistics for baseline
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct TimingStatistics {
157    /// Mean execution time
158    pub mean: f64,
159    /// Standard deviation
160    pub std_dev: f64,
161    /// Median
162    pub median: f64,
163    /// Interquartile range
164    pub iqr: f64,
165    /// Coefficient of variation
166    pub coefficient_of_variation: f64,
167}
168
169/// Memory statistics for baseline
170#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct MemoryStatistics {
172    /// Mean memory usage
173    pub mean_memory: f64,
174    /// Standard deviation
175    pub std_dev_memory: f64,
176    /// Peak memory percentiles
177    pub peak_memory_percentiles: HashMap<String, f64>,
178    /// Fragmentation statistics
179    pub fragmentation_stats: FragmentationStatistics,
180}
181
182/// Fragmentation statistics
183#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct FragmentationStatistics {
185    /// Mean fragmentation ratio
186    pub mean_ratio: f64,
187    /// Standard deviation
188    pub std_dev_ratio: f64,
189    /// Trend analysis
190    pub trend: f64,
191}
192
193/// Efficiency statistics for baseline
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct EfficiencyStatistics<A: Float> {
196    /// Mean FLOPS
197    pub mean_flops: f64,
198    /// FLOPS variability
199    pub flops_cv: f64,
200    /// Mean efficiency score
201    pub mean_efficiency: f64,
202    /// Custom efficiency metrics
203    pub custom_efficiency: HashMap<String, A>,
204}
205
206/// Convergence statistics for baseline
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct ConvergenceStatistics<A: Float> {
209    /// Mean final objective
210    pub mean_objective: A,
211    /// Objective standard deviation
212    pub std_objective: A,
213    /// Mean convergence rate
214    pub mean_convergence_rate: f64,
215    /// Convergence consistency
216    pub convergence_consistency: f64,
217}
218
219/// Confidence intervals for baseline metrics
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct ConfidenceIntervals {
222    /// 95% confidence intervals for timing
223    pub timing_ci_95: (f64, f64),
224    /// 95% confidence intervals for memory
225    pub memory_ci_95: (f64, f64),
226    /// 99% confidence intervals for timing
227    pub timing_ci_99: (f64, f64),
228    /// 99% confidence intervals for memory
229    pub memory_ci_99: (f64, f64),
230}
231
232/// Regression detection result
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct RegressionResult<A: Float> {
235    /// Test identifier
236    pub test_id: String,
237    /// Regression detected
238    pub regression_detected: bool,
239    /// Regression severity (0.0 to 1.0)
240    pub severity: f64,
241    /// Confidence level (0.0 to 1.0)
242    pub confidence: f64,
243    /// Performance change percentage
244    pub performance_change_percent: f64,
245    /// Memory change percentage
246    pub memory_change_percent: f64,
247    /// Affected metrics
248    pub affected_metrics: Vec<String>,
249    /// Statistical test results
250    pub statistical_tests: Vec<StatisticalTestResult>,
251    /// Detailed analysis
252    pub analysis: RegressionAnalysis<A>,
253    /// Recommendations
254    pub recommendations: Vec<String>,
255}
256
257/// Statistical test result
258#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct StatisticalTestResult {
260    /// Test name
261    pub test_name: String,
262    /// Test statistic value
263    pub test_statistic: f64,
264    /// P-value
265    pub p_value: f64,
266    /// Degrees of freedom
267    pub degrees_of_freedom: Option<usize>,
268    /// Test conclusion
269    pub conclusion: String,
270}
271
272/// Detailed regression analysis
273#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct RegressionAnalysis<A: Float> {
275    /// Trend analysis
276    pub trend_analysis: TrendAnalysis,
277    /// Change point analysis
278    pub change_point_analysis: ChangePointAnalysis,
279    /// Outlier analysis
280    pub outlier_analysis: OutlierAnalysis<A>,
281    /// Root cause analysis hints
282    pub root_cause_hints: Vec<String>,
283}
284
285/// Trend analysis results
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct TrendAnalysis {
288    /// Trend direction
289    pub direction: TrendDirection,
290    /// Trend magnitude
291    pub magnitude: f64,
292    /// Trend significance
293    pub significance: f64,
294    /// Trend starting point
295    pub start_point: Option<usize>,
296}
297
298/// Trend direction
299#[derive(Debug, Clone, Serialize, Deserialize)]
300pub enum TrendDirection {
301    /// Performance is improving
302    Improving,
303    /// Performance is stable
304    Stable,
305    /// Performance is degrading
306    Degrading,
307    /// Performance is volatile/inconsistent
308    Volatile,
309}
310
311/// Change point analysis
312#[derive(Debug, Clone, Serialize, Deserialize)]
313pub struct ChangePointAnalysis {
314    /// Change points detected
315    pub change_points: Vec<usize>,
316    /// Change magnitudes
317    pub magnitudes: Vec<f64>,
318    /// Confidence levels
319    pub confidences: Vec<f64>,
320}
321
322/// Outlier analysis
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct OutlierAnalysis<A: Float> {
325    /// Outlier indices
326    pub outlier_indices: Vec<usize>,
327    /// Outlier scores
328    pub outlier_scores: Vec<A>,
329    /// Outlier types
330    pub outlier_types: Vec<OutlierType>,
331}
332
333/// Types of outliers
334#[derive(Debug, Clone, Serialize, Deserialize)]
335pub enum OutlierType {
336    /// Single extreme value
337    Point,
338    /// Shift in distribution
339    Shift,
340    /// Trend change
341    Trend,
342    /// Increased variance
343    Variance,
344}
345
346/// Regression detection algorithm trait
347pub trait RegressionDetector<A: Float>: Debug {
348    /// Detect regression in performance data
349    fn detect_regression(
350        &self,
351        baseline: &PerformanceBaseline<A>,
352        current_metrics: &PerformanceMetrics<A>,
353        history: &VecDeque<PerformanceRecord<A>>,
354    ) -> Result<RegressionResult<A>>;
355
356    /// Get detector name
357    fn name(&self) -> &str;
358
359    /// Get detector configuration
360    fn config(&self) -> HashMap<String, String>;
361}
362
363/// Statistical analysis trait
364pub trait StatisticalAnalyzer<A: Float>: Debug {
365    /// Perform statistical analysis on performance data
366    fn analyze(
367        &self,
368        data: &VecDeque<PerformanceRecord<A>>,
369    ) -> Result<StatisticalAnalysisResult<A>>;
370
371    /// Get analyzer name
372    fn name(&self) -> &str;
373}
374
375/// Statistical analysis result
376#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct StatisticalAnalysisResult<A: Float> {
378    /// Analysis summary
379    pub summary: String,
380    /// Statistical tests performed
381    pub tests: Vec<StatisticalTestResult>,
382    /// Detected patterns
383    pub patterns: Vec<String>,
384    /// Anomalies detected
385    pub anomalies: Vec<A>,
386}
387
388impl<A: Float + Send + Sync> Default for PerformanceMetrics<A> {
389    fn default() -> Self {
390        Self {
391            timing: TimingMetrics::default(),
392            memory: MemoryMetrics::default(),
393            efficiency: EfficiencyMetrics::default(),
394            convergence: ConvergenceMetrics::default(),
395            custom: HashMap::new(),
396        }
397    }
398}
399
400impl Default for MemoryMetrics {
401    fn default() -> Self {
402        Self {
403            peak_memory_bytes: 0,
404            avg_memory_bytes: 0,
405            allocation_count: 0,
406            fragmentation_ratio: 0.0,
407            efficiency_score: 0.0,
408        }
409    }
410}
411
412impl<A: Float + Send + Sync> Default for EfficiencyMetrics<A> {
413    fn default() -> Self {
414        Self {
415            flops: 0.0,
416            arithmetic_intensity: 0.0,
417            cache_hit_ratio: 0.0,
418            cpu_utilization: 0.0,
419            efficiency_score: 0.0,
420            custom_metrics: HashMap::new(),
421        }
422    }
423}
424
425impl<A: Float + Send + Sync> Default for ConvergenceMetrics<A> {
426    fn default() -> Self {
427        Self {
428            final_objective: A::zero(),
429            convergence_rate: 0.0,
430            iterations_to_convergence: None,
431            quality_score: 0.0,
432            stability_score: 0.0,
433        }
434    }
435}
436
437impl Default for DatabaseMetadata {
438    fn default() -> Self {
439        use std::time::{SystemTime, UNIX_EPOCH};
440
441        let now = SystemTime::now()
442            .duration_since(UNIX_EPOCH)
443            .unwrap_or_default()
444            .as_secs();
445
446        Self {
447            version: "1.0.0".to_string(),
448            created_at: now,
449            last_updated: now,
450            total_records: 0,
451        }
452    }
453}
454
455#[cfg(test)]
456mod tests {
457    use super::*;
458
459    #[test]
460    fn test_performance_metrics_default() {
461        let metrics: PerformanceMetrics<f64> = PerformanceMetrics::default();
462        assert_eq!(metrics.timing.mean_time_ns, 0);
463        assert_eq!(metrics.memory.peak_memory_bytes, 0);
464        assert_eq!(metrics.efficiency.flops, 0.0);
465        assert_eq!(metrics.convergence.final_objective, 0.0);
466        assert!(metrics.custom.is_empty());
467    }
468
469    #[test]
470    fn test_database_metadata_default() {
471        let metadata = DatabaseMetadata::default();
472        assert_eq!(metadata.version, "1.0.0");
473        assert_eq!(metadata.total_records, 0);
474        assert!(metadata.created_at > 0);
475        assert!(metadata.last_updated > 0);
476    }
477
478    #[test]
479    fn test_trend_direction_variants() {
480        assert!(matches!(
481            TrendDirection::Improving,
482            TrendDirection::Improving
483        ));
484        assert!(matches!(TrendDirection::Stable, TrendDirection::Stable));
485        assert!(matches!(
486            TrendDirection::Degrading,
487            TrendDirection::Degrading
488        ));
489        assert!(matches!(TrendDirection::Volatile, TrendDirection::Volatile));
490    }
491
492    #[test]
493    fn test_outlier_type_variants() {
494        assert!(matches!(OutlierType::Point, OutlierType::Point));
495        assert!(matches!(OutlierType::Shift, OutlierType::Shift));
496        assert!(matches!(OutlierType::Trend, OutlierType::Trend));
497        assert!(matches!(OutlierType::Variance, OutlierType::Variance));
498    }
499}