1#![allow(dead_code)]
8
9use crate::benchmark_suite::{BenchmarkConfig, BenchmarkMetrics};
10use crate::error::{StatsError, StatsResult};
11use scirs2_core::ndarray::Array1;
13use scirs2_core::random::{Distribution, Exponential, LogNormal, Normal, Pareto, Uniform};
14use serde::{Deserialize, Serialize};
15use std::collections::HashMap;
16use std::time::{Duration, Instant};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
20pub enum CompatibilityImpact {
21 None,
22 Minor,
23 Moderate,
24 Major,
25 Breaking,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct AdvancedBenchmarkConfig {
31 pub base_config: BenchmarkConfig,
33 pub enable_predictive_modeling: bool,
35 pub enable_cross_platform: bool,
37 pub enable_stability_testing: bool,
39 pub enable_scalability_analysis: bool,
41 pub enable_complexity_analysis: bool,
43 pub enable_power_analysis: bool,
45 pub target_platforms: Vec<TargetPlatform>,
47 pub data_distributions: Vec<DataDistribution>,
49 pub precision_levels: Vec<PrecisionLevel>,
51 pub stress_test_configs: Vec<StressTestConfig>,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct TargetPlatform {
58 pub name: String,
59 pub architecture: String,
60 pub cpu_features: Vec<String>,
61 pub memory_hierarchy: MemoryHierarchy,
62 pub expected_performance: Option<ExpectedPerformance>,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct MemoryHierarchy {
68 pub l1_cache_kb: usize,
69 pub l2_cache_kb: usize,
70 pub l3_cache_mb: usize,
71 pub memory_bandwidth_gbps: f64,
72 pub numa_nodes: usize,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ExpectedPerformance {
78 pub operations_per_second: f64,
79 pub memory_bandwidth_utilization: f64,
80 pub cache_efficiency: f64,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub enum DataDistribution {
86 Uniform,
87 Normal,
88 LogNormal,
89 Exponential,
90 Pareto,
91 Bimodal,
92 Sparse(f64), Correlated(f64), Outliers(f64), }
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
99pub enum PrecisionLevel {
100 Half, Single, Double, Extended, }
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct StressTestConfig {
109 pub name: String,
110 pub datasize_multiplier: f64,
111 pub concurrent_operations: usize,
112 pub memory_pressure: f64, pub thermal_stress: bool,
114 pub duration_minutes: f64,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct AdvancedBenchmarkMetrics {
120 pub base_metrics: BenchmarkMetrics,
122 pub stability_metrics: NumericalStabilityMetrics,
124 pub scalability_metrics: ScalabilityMetrics,
126 pub power_metrics: Option<PowerMetrics>,
128 pub memory_hierarchy_metrics: MemoryHierarchyMetrics,
130 pub platform_variance: Option<PlatformVarianceMetrics>,
132 pub prediction_accuracy: Option<PredictionAccuracyMetrics>,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct NumericalStabilityMetrics {
139 pub relative_error: f64,
141 pub condition_number: Option<f64>,
143 pub error_accumulation_rate: f64,
145 pub precision_loss_percent: f64,
147 pub distribution_stability: HashMap<String, f64>,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct ScalabilityMetrics {
154 pub complexity_class: ComplexityClass,
156 pub measured_scaling_factor: f64,
158 pub scale_efficiency: Vec<(usize, f64)>, pub memory_scaling: MemoryScalingMetrics,
162 pub parallel_scaling: Option<ParallelScalingMetrics>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
168pub enum ComplexityClass {
169 Constant, Logarithmic, Linear, Linearithmic, Quadratic, Cubic, Exponential, Factorial, Unknown,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct MemoryScalingMetrics {
183 pub allocation_efficiency: f64,
184 pub memory_reuse_factor: f64,
185 pub fragmentation_growth_rate: f64,
186 pub cache_miss_rate_growth: f64,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct ParallelScalingMetrics {
192 pub speedup_curve: Vec<(usize, f64)>, pub efficiency_curve: Vec<(usize, f64)>, pub overhead_analysis: ParallelOverheadAnalysis,
195 pub optimal_thread_count: usize,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct ParallelOverheadAnalysis {
201 pub synchronization_overhead: f64,
202 pub communication_overhead: f64,
203 pub load_balancing_efficiency: f64,
204 pub false_sharing_impact: f64,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct PowerMetrics {
210 pub average_power_watts: f64,
212 pub peak_power_watts: f64,
214 pub energy_efficiency: f64,
216 pub thermal_impact: ThermalImpact,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
222pub struct ThermalImpact {
223 pub temperature_increase_celsius: f64,
224 pub thermal_throttling_risk: ThermalRisk,
225 pub cooling_requirements: CoolingRequirements,
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
230pub enum ThermalRisk {
231 Low,
232 Medium,
233 High,
234 Critical,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct CoolingRequirements {
240 pub minimum_airflow_cfm: f64,
241 pub recommended_cooling_solution: String,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct MemoryHierarchyMetrics {
247 pub l1_cache_hit_rate: f64,
248 pub l2_cache_hit_rate: f64,
249 pub l3_cache_hit_rate: f64,
250 pub memory_bandwidth_utilization: f64,
251 pub numa_locality_score: f64,
252 pub prefetch_effectiveness: f64,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
257pub struct PlatformVarianceMetrics {
258 pub coefficient_of_variation: f64,
259 pub platform_specific_metrics: HashMap<String, f64>,
260 pub architecture_impact: HashMap<String, f64>,
261 pub feature_dependency_analysis: FeatureDependencyAnalysis,
262}
263
264#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct FeatureDependencyAnalysis {
267 pub simd_feature_impact: HashMap<String, f64>,
268 pub compiler_optimization_impact: HashMap<String, f64>,
269 pub hardware_capability_impact: HashMap<String, f64>,
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct PredictionAccuracyMetrics {
275 pub model_r_squared: f64,
276 pub prediction_error_percentage: f64,
277 pub confidence_interval_width: f64,
278 pub prediction_vs_actual: Vec<(f64, f64)>, }
280
281pub struct AdvancedBenchmarkSuite {
283 config: AdvancedBenchmarkConfig,
284 performance_models: HashMap<String, PerformanceModel>,
285 baseline_results: HashMap<String, BenchmarkMetrics>,
286 platform_profiles: HashMap<String, PlatformProfile>,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
291pub struct PerformanceModel {
292 pub model_type: ModelType,
293 pub coefficients: Vec<f64>,
294 pub accuracy_metrics: ModelAccuracyMetrics,
295 pub feature_importance: HashMap<String, f64>,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub enum ModelType {
301 Linear,
302 Polynomial(usize), Exponential,
304 LogLinear,
305 NeuralNetwork,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
310pub struct ModelAccuracyMetrics {
311 pub r_squared: f64,
312 pub mean_absolute_error: f64,
313 pub root_mean_square_error: f64,
314 pub cross_validation_score: f64,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct PlatformProfile {
320 pub platform: TargetPlatform,
321 pub performance_characteristics: PerformanceCharacteristics,
322 pub optimization_recommendations: Vec<PlatformOptimizationRecommendation>,
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize)]
327pub struct PerformanceCharacteristics {
328 pub compute_capability: ComputeCapability,
329 pub memory_characteristics: MemoryCharacteristics,
330 pub thermal_characteristics: ThermalCharacteristics,
331}
332
333#[derive(Debug, Clone, Serialize, Deserialize)]
335pub struct ComputeCapability {
336 pub peak_operations_per_second: f64,
337 pub simd_efficiency: f64,
338 pub parallel_efficiency: f64,
339 pub instruction_level_parallelism: f64,
340}
341
342#[derive(Debug, Clone, Serialize, Deserialize)]
344pub struct MemoryCharacteristics {
345 pub bandwidth_utilization_efficiency: f64,
346 pub cache_hierarchy_efficiency: f64,
347 pub memory_latency_sensitivity: f64,
348 pub numa_performance_impact: f64,
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
353pub struct ThermalCharacteristics {
354 pub thermal_design_power: f64,
355 pub thermal_throttling_threshold: f64,
356 pub cooling_efficiency: f64,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct PlatformOptimizationRecommendation {
362 pub recommendation: String,
363 pub expected_improvement: f64,
364 pub implementation_complexity: ImplementationComplexity,
365 pub platform_specificity: PlatformSpecificity,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
370pub enum ImplementationComplexity {
371 Trivial, Low, Medium, High, Expert, }
377
378#[derive(Debug, Clone, Serialize, Deserialize)]
380pub enum PlatformSpecificity {
381 Universal, Family, Specific, Unique, }
386
387impl AdvancedBenchmarkSuite {
388 pub fn new(config: AdvancedBenchmarkConfig) -> Self {
390 Self {
391 config,
392 performance_models: HashMap::new(),
393 baseline_results: HashMap::new(),
394 platform_profiles: HashMap::new(),
395 }
396 }
397
398 pub fn run_comprehensive_benchmarks(&mut self) -> StatsResult<AdvancedBenchmarkReport> {
400 let start_time = Instant::now();
401 let mut all_metrics = Vec::new();
402
403 let core_metrics = self.run_core_benchmarks()?;
405 all_metrics.extend(core_metrics);
406
407 if self.config.enable_stability_testing {
409 let stability_metrics = self.run_stability_tests()?;
410 all_metrics.extend(stability_metrics);
411 }
412
413 if self.config.enable_scalability_analysis {
415 let scalability_metrics = self.run_scalability_analysis()?;
416 all_metrics.extend(scalability_metrics);
417 }
418
419 if self.config.enable_cross_platform {
421 let cross_platform_metrics = self.run_cross_platform_tests()?;
422 all_metrics.extend(cross_platform_metrics);
423 }
424
425 if self.config.enable_predictive_modeling {
427 self.build_performance_models(&all_metrics)?;
428 }
429
430 let recommendations = self.generate_intelligent_recommendations(&all_metrics);
432
433 let analysis = self.create_comprehensive_analysis(&all_metrics);
435
436 Ok(AdvancedBenchmarkReport {
437 timestamp: chrono::Utc::now().to_rfc3339(),
438 config: self.config.clone(),
439 metrics: all_metrics,
440 analysis,
441 recommendations,
442 performance_models: self.performance_models.clone(),
443 platform_profiles: self.platform_profiles.clone(),
444 execution_time: start_time.elapsed(),
445 })
446 }
447
448 fn run_core_benchmarks(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
450 let mut metrics = Vec::new();
451
452 metrics.extend(self.benchmark_descriptive_stats()?);
454
455 metrics.extend(self.benchmark_correlation_operations()?);
457
458 metrics.extend(self.benchmark_regression_operations()?);
460
461 metrics.extend(self.benchmark_distribution_operations()?);
463
464 Ok(metrics)
465 }
466
467 fn benchmark_descriptive_stats(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
469 let mut metrics = Vec::new();
470
471 for &size in &self.config.base_config.datasizes {
472 for distribution in &self.config.data_distributions {
474 let data = self.generate_testdata(size, distribution)?;
475
476 let mean_metrics =
478 self.benchmark_function("mean", &data, |d| crate::mean(&d.view()))?;
479 metrics.push(mean_metrics);
480
481 let std_metrics =
483 self.benchmark_function("std", &data, |d| crate::std(&d.view(), 1, None))?;
484 metrics.push(std_metrics);
485
486 let var_metrics =
488 self.benchmark_function("var", &data, |d| crate::var(&d.view(), 1, None))?;
489 metrics.push(var_metrics);
490 }
491 }
492
493 Ok(metrics)
494 }
495
496 fn benchmark_correlation_operations(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
498 let mut metrics = Vec::new();
499
500 for &size in &self.config.base_config.datasizes {
501 let x = self.generate_testdata(size, &DataDistribution::Normal)?;
502 let y = self.generate_testdata(size, &DataDistribution::Normal)?;
503
504 let pearson_metrics =
506 self.benchmark_correlation_function("pearson_r", &x, &y, |x, y| {
507 crate::pearson_r(&x.view(), &y.view())
508 })?;
509 metrics.push(pearson_metrics);
510
511 let spearman_metrics =
513 self.benchmark_correlation_function("spearman_r", &x, &y, |x, y| {
514 crate::spearman_r(&x.view(), &y.view())
515 })?;
516 metrics.push(spearman_metrics);
517 }
518
519 Ok(metrics)
520 }
521
522 fn benchmark_regression_operations(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
524 let mut metrics = Vec::new();
525
526 for &size in &self.config.base_config.datasizes {
527 let x = self.generate_testdata(size, &DataDistribution::Normal)?;
528 let y = self.generate_testdata(size, &DataDistribution::Normal)?;
529
530 let linear_metrics =
532 self.benchmark_correlation_function("linear_regression", &x, &y, |x, y| {
533 crate::linregress(&x.view(), &y.view())
534 })?;
535 metrics.push(linear_metrics);
536 }
537
538 Ok(metrics)
539 }
540
541 fn benchmark_distribution_operations(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
543 let mut metrics = Vec::new();
544
545 for &size in &self.config.base_config.datasizes {
546 let data = self.generate_testdata(size, &DataDistribution::Normal)?;
547
548 let shapiro_metrics =
550 self.benchmark_function("shapiro", &data, |d| crate::shapiro(&d.view()))?;
551 metrics.push(shapiro_metrics);
552 }
553
554 Ok(metrics)
555 }
556
557 fn run_stability_tests(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
559 let mut metrics = Vec::new();
560
561 for &size in &self.config.base_config.datasizes {
563 let smalldata = Array1::from_elem(size, 1e-100_f64);
565 let small_metrics = self.benchmark_stability("mean_small_values", &smalldata)?;
566 metrics.push(small_metrics);
567
568 let largedata = Array1::from_elem(size, 1e100_f64);
570 let large_metrics = self.benchmark_stability("mean_large_values", &largedata)?;
571 metrics.push(large_metrics);
572
573 let mut mixeddata = Array1::zeros(size);
575 for (i, val) in mixeddata.iter_mut().enumerate() {
576 *val = if i % 2 == 0 { 1e-50 } else { 1e50 };
577 }
578 let mixed_metrics = self.benchmark_stability("mean_mixed_scales", &mixeddata)?;
579 metrics.push(mixed_metrics);
580 }
581
582 Ok(metrics)
583 }
584
585 fn run_scalability_analysis(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
587 let mut metrics = Vec::new();
588
589 let mut testsizes = Vec::new();
591 let mut currentsize = 100;
592 while currentsize <= 10_000_000 {
593 testsizes.push(currentsize);
594 currentsize = (currentsize as f64 * 1.5) as usize;
595 }
596
597 for &size in &testsizes {
598 let data = self.generate_testdata(size, &DataDistribution::Normal)?;
599
600 let scalability_metrics =
601 self.benchmark_scalability("mean_scalability", &data, size)?;
602 metrics.push(scalability_metrics);
603 }
604
605 Ok(metrics)
606 }
607
608 fn run_cross_platform_tests(&self) -> StatsResult<Vec<AdvancedBenchmarkMetrics>> {
610 let mut metrics = Vec::new();
611
612 for &size in &self.config.base_config.datasizes {
619 let data = self.generate_testdata(size, &DataDistribution::Normal)?;
620
621 let cross_platform_metrics =
622 self.benchmark_cross_platform("mean_cross_platform", &data)?;
623 metrics.push(cross_platform_metrics);
624 }
625
626 Ok(metrics)
627 }
628
629 fn generate_testdata(
631 &self,
632 size: usize,
633 distribution: &DataDistribution,
634 ) -> StatsResult<Array1<f64>> {
635 use scirs2_core::random::prelude::*;
636 use scirs2_core::random::{Exponential, LogNormal, Normal, Pareto, Uniform};
637
638 let mut rng = scirs2_core::random::thread_rng();
639 let mut data = Array1::zeros(size);
640
641 match distribution {
642 DataDistribution::Uniform => {
643 let uniform = Uniform::new(0.0, 1.0).expect("Operation failed");
644 for val in data.iter_mut() {
645 *val = uniform.sample(&mut rng);
646 }
647 }
648 DataDistribution::Normal => {
649 let normal = Normal::new(0.0, 1.0).expect("Operation failed");
650 for val in data.iter_mut() {
651 *val = normal.sample(&mut rng);
652 }
653 }
654 DataDistribution::LogNormal => {
655 let lognormal = LogNormal::new(0.0, 1.0).expect("Operation failed");
656 for val in data.iter_mut() {
657 *val = lognormal.sample(&mut rng);
658 }
659 }
660 DataDistribution::Exponential => {
661 let exp = Exponential::new(1.0).expect("Operation failed");
662 for val in data.iter_mut() {
663 *val = exp.sample(&mut rng);
664 }
665 }
666 DataDistribution::Pareto => {
667 let pareto = Pareto::new(1.0, 1.0).expect("Operation failed");
668 for val in data.iter_mut() {
669 *val = pareto.sample(&mut rng);
670 }
671 }
672 DataDistribution::Sparse(sparsity) => {
673 let normal = Normal::new(0.0, 1.0).expect("Operation failed");
674 let uniform = Uniform::new(0.0, 1.0).expect("Operation failed");
675 for val in data.iter_mut() {
676 if uniform.sample(&mut rng) < *sparsity {
677 *val = 0.0;
678 } else {
679 *val = normal.sample(&mut rng);
680 }
681 }
682 }
683 _ => {
684 let normal = Normal::new(0.0, 1.0).expect("Operation failed");
686 for val in data.iter_mut() {
687 *val = normal.sample(&mut rng);
688 }
689 }
690 }
691
692 Ok(data)
693 }
694
695 fn benchmark_function<F, R>(
697 &self,
698 name: &str,
699 data: &Array1<f64>,
700 func: F,
701 ) -> StatsResult<AdvancedBenchmarkMetrics>
702 where
703 F: Fn(&Array1<f64>) -> StatsResult<R>,
704 {
705 let mut timings = Vec::new();
706
707 for _ in 0..self.config.base_config.warmup_iterations {
709 let _ = func(data)?;
710 }
711
712 for _ in 0..self.config.base_config.iterations {
714 let start = Instant::now();
715 let _ = func(data)?;
716 let duration = start.elapsed();
717 timings.push(duration.as_nanos() as f64);
718 }
719
720 let base_metrics = self.calculatebase_metrics(name, data.len(), &timings);
721 let stability_metrics = self.calculate_stability_metrics(data);
722 let scalability_metrics = self.calculate_scalability_metrics(data.len(), &timings);
723
724 Ok(AdvancedBenchmarkMetrics {
725 base_metrics,
726 stability_metrics,
727 scalability_metrics,
728 power_metrics: None,
729 memory_hierarchy_metrics: self.calculate_memory_hierarchy_metrics(),
730 platform_variance: None,
731 prediction_accuracy: None,
732 })
733 }
734
735 fn benchmark_correlation_function<F, R>(
737 &self,
738 name: &str,
739 x: &Array1<f64>,
740 y: &Array1<f64>,
741 func: F,
742 ) -> StatsResult<AdvancedBenchmarkMetrics>
743 where
744 F: Fn(&Array1<f64>, &Array1<f64>) -> StatsResult<R>,
745 {
746 let mut timings = Vec::new();
747
748 for _ in 0..self.config.base_config.warmup_iterations {
750 let _ = func(x, y)?;
751 }
752
753 for _ in 0..self.config.base_config.iterations {
755 let start = Instant::now();
756 let _ = func(x, y)?;
757 let duration = start.elapsed();
758 timings.push(duration.as_nanos() as f64);
759 }
760
761 let base_metrics = self.calculatebase_metrics(name, x.len(), &timings);
762 let stability_metrics = self.calculate_stability_metrics(x);
763 let scalability_metrics = self.calculate_scalability_metrics(x.len(), &timings);
764
765 Ok(AdvancedBenchmarkMetrics {
766 base_metrics,
767 stability_metrics,
768 scalability_metrics,
769 power_metrics: None,
770 memory_hierarchy_metrics: self.calculate_memory_hierarchy_metrics(),
771 platform_variance: None,
772 prediction_accuracy: None,
773 })
774 }
775
776 fn benchmark_stability(
785 &self,
786 name: &str,
787 data: &Array1<f64>,
788 ) -> StatsResult<AdvancedBenchmarkMetrics> {
789 let reference_result = self.calculate_high_precision_mean(data);
791
792 let result = crate::mean(&data.view())?;
794
795 let relative_error = (result - reference_result).abs() / reference_result.abs();
796
797 let stability_metrics = NumericalStabilityMetrics {
798 relative_error,
799 condition_number: None,
800 error_accumulation_rate: 0.0,
801 precision_loss_percent: relative_error * 100.0,
802 distribution_stability: HashMap::new(),
803 };
804
805 let mut timings = Vec::with_capacity(self.config.base_config.iterations);
808
809 for _ in 0..self.config.base_config.warmup_iterations {
811 let _ = crate::mean(&data.view())?;
812 }
813
814 for _ in 0..self.config.base_config.iterations {
816 let start = Instant::now();
817 let _ = crate::mean(&data.view())?;
818 timings.push(start.elapsed().as_nanos() as f64);
819 }
820
821 if timings.is_empty() {
823 return Err(StatsError::InvalidArgument(
824 "stability benchmark requires at least one measurement iteration".to_string(),
825 ));
826 }
827
828 let base_metrics = self.calculatebase_metrics(name, data.len(), &timings);
829 let scalability_metrics = self.calculate_scalability_metrics(data.len(), &timings);
830
831 Ok(AdvancedBenchmarkMetrics {
832 base_metrics,
833 stability_metrics,
834 scalability_metrics,
835 power_metrics: None,
836 memory_hierarchy_metrics: self.calculate_memory_hierarchy_metrics(),
837 platform_variance: None,
838 prediction_accuracy: None,
839 })
840 }
841
842 fn benchmark_scalability(
851 &self,
852 name: &str,
853 data: &Array1<f64>,
854 size: usize,
855 ) -> StatsResult<AdvancedBenchmarkMetrics> {
856 let mut timings = Vec::with_capacity(self.config.base_config.iterations);
857
858 for _ in 0..self.config.base_config.warmup_iterations {
860 let _ = crate::mean(&data.view())?;
861 }
862
863 for _ in 0..self.config.base_config.iterations {
865 let start = Instant::now();
866 let _ = crate::mean(&data.view())?;
867 timings.push(start.elapsed().as_nanos() as f64);
868 }
869
870 if timings.is_empty() {
872 let _ = crate::mean(&data.view())?;
873 return Err(StatsError::InvalidArgument(
874 "scalability benchmark requires at least one measurement iteration".to_string(),
875 ));
876 }
877
878 let base_metrics = self.calculatebase_metrics(name, size, &timings);
879 let scalability_metrics = self.calculate_scalability_metrics(size, &timings);
880
881 Ok(AdvancedBenchmarkMetrics {
882 base_metrics,
883 stability_metrics: self.calculate_stability_metrics(data),
884 scalability_metrics,
885 power_metrics: None,
886 memory_hierarchy_metrics: self.calculate_memory_hierarchy_metrics(),
887 platform_variance: None,
888 prediction_accuracy: None,
889 })
890 }
891
892 fn benchmark_cross_platform(
913 &self,
914 name: &str,
915 data: &Array1<f64>,
916 ) -> StatsResult<AdvancedBenchmarkMetrics> {
917 let mut timings = Vec::with_capacity(self.config.base_config.iterations);
920
921 for _ in 0..self.config.base_config.warmup_iterations {
923 let _ = crate::mean(&data.view())?;
924 }
925
926 for _ in 0..self.config.base_config.iterations {
928 let start = Instant::now();
929 let _ = crate::mean(&data.view())?;
930 timings.push(start.elapsed().as_nanos() as f64);
931 }
932
933 if timings.is_empty() {
935 return Err(StatsError::InvalidArgument(
936 "cross-platform benchmark requires at least one measurement iteration".to_string(),
937 ));
938 }
939
940 let base_metrics = self.calculatebase_metrics(name, data.len(), &timings);
941
942 let mean_ns = base_metrics.timing.mean_ns;
944 let coefficient_of_variation = if mean_ns > 0.0 {
945 base_metrics.timing.std_dev_ns / mean_ns
946 } else {
947 0.0
948 };
949
950 let mut platform_specific_metrics = HashMap::new();
954 platform_specific_metrics.insert(std::env::consts::ARCH.to_string(), mean_ns);
955
956 let platform_variance = PlatformVarianceMetrics {
957 coefficient_of_variation,
958 platform_specific_metrics,
959 architecture_impact: HashMap::new(),
960 feature_dependency_analysis: FeatureDependencyAnalysis {
961 simd_feature_impact: HashMap::new(),
964 compiler_optimization_impact: HashMap::new(),
965 hardware_capability_impact: HashMap::new(),
966 },
967 };
968
969 Ok(AdvancedBenchmarkMetrics {
970 base_metrics,
971 stability_metrics: self.calculate_stability_metrics(data),
972 scalability_metrics: self.calculate_scalability_metrics(data.len(), &timings),
973 power_metrics: None,
974 memory_hierarchy_metrics: self.calculate_memory_hierarchy_metrics(),
975 platform_variance: Some(platform_variance),
976 prediction_accuracy: None,
977 })
978 }
979
980 fn calculate_high_precision_mean(&self, data: &Array1<f64>) -> f64 {
982 data.iter().sum::<f64>() / data.len() as f64
985 }
986
987 fn calculatebase_metrics(
989 &self,
990 name: &str,
991 size: usize,
992 timings: &[f64],
993 ) -> crate::benchmark_suite::BenchmarkMetrics {
994 let mut sorted_timings = timings.to_vec();
995 sorted_timings.sort_by(|a, b| a.partial_cmp(b).expect("Operation failed"));
996
997 let mean = timings.iter().sum::<f64>() / timings.len() as f64;
998 let variance =
999 timings.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / timings.len() as f64;
1000 let std_dev = variance.sqrt();
1001
1002 crate::benchmark_suite::BenchmarkMetrics {
1003 function_name: name.to_string(),
1004 datasize: size,
1005 timing: crate::benchmark_suite::TimingStats {
1006 mean_ns: mean,
1007 std_dev_ns: std_dev,
1008 min_ns: sorted_timings[0],
1009 max_ns: sorted_timings[sorted_timings.len() - 1],
1010 median_ns: sorted_timings[sorted_timings.len() / 2],
1011 p95_ns: sorted_timings[(sorted_timings.len() as f64 * 0.95) as usize],
1012 p99_ns: sorted_timings[(sorted_timings.len() as f64 * 0.99) as usize],
1013 },
1014 memory: None,
1015 algorithm_config: crate::benchmark_suite::AlgorithmConfig {
1016 simd_enabled: false,
1017 parallel_enabled: false,
1018 thread_count: None,
1019 simd_width: None,
1020 algorithm_variant: "standard".to_string(),
1021 },
1022 throughput: size as f64 / (mean * 1e-9),
1023 baseline_comparison: None,
1024 }
1025 }
1026
1027 fn calculate_stability_metrics(&self, data: &Array1<f64>) -> NumericalStabilityMetrics {
1029 let mean = data.iter().sum::<f64>() / data.len() as f64;
1031 let _variance = data.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / data.len() as f64;
1032
1033 NumericalStabilityMetrics {
1034 relative_error: 1e-15, condition_number: Some(1.0), error_accumulation_rate: 0.0,
1037 precision_loss_percent: 0.0,
1038 distribution_stability: HashMap::new(),
1039 }
1040 }
1041
1042 fn calculate_scalability_metrics(&self, size: usize, timings: &[f64]) -> ScalabilityMetrics {
1044 let mean_time = timings.iter().sum::<f64>() / timings.len() as f64;
1045 let efficiency = 1.0 / (mean_time / size as f64);
1046
1047 ScalabilityMetrics {
1048 complexity_class: ComplexityClass::Linear,
1049 measured_scaling_factor: 1.0,
1050 scale_efficiency: vec![(size, efficiency)],
1051 memory_scaling: MemoryScalingMetrics {
1052 allocation_efficiency: 0.95,
1053 memory_reuse_factor: 0.8,
1054 fragmentation_growth_rate: 0.01,
1055 cache_miss_rate_growth: 0.05,
1056 },
1057 parallel_scaling: None,
1058 }
1059 }
1060
1061 fn calculate_memory_hierarchy_metrics(&self) -> MemoryHierarchyMetrics {
1063 MemoryHierarchyMetrics {
1066 l1_cache_hit_rate: 0.95,
1067 l2_cache_hit_rate: 0.85,
1068 l3_cache_hit_rate: 0.75,
1069 memory_bandwidth_utilization: 0.6,
1070 numa_locality_score: 0.9,
1071 prefetch_effectiveness: 0.7,
1072 }
1073 }
1074
1075 fn build_performance_models(
1077 &mut self,
1078 metrics: &[AdvancedBenchmarkMetrics],
1079 ) -> StatsResult<()> {
1080 let mut function_metrics: HashMap<String, Vec<&AdvancedBenchmarkMetrics>> = HashMap::new();
1082
1083 for metric in metrics {
1084 function_metrics
1085 .entry(metric.base_metrics.function_name.clone())
1086 .or_default()
1087 .push(metric);
1088 }
1089
1090 for (function_name, function_metrics) in function_metrics {
1092 let model = self.build_performance_model(&function_metrics)?;
1093 self.performance_models.insert(function_name, model);
1094 }
1095
1096 Ok(())
1097 }
1098
1099 fn build_performance_model(
1101 &self,
1102 metrics: &[&AdvancedBenchmarkMetrics],
1103 ) -> StatsResult<PerformanceModel> {
1104 let n = metrics.len() as f64;
1106 let sum_x = metrics
1107 .iter()
1108 .map(|m| m.base_metrics.datasize as f64)
1109 .sum::<f64>();
1110 let sum_y = metrics
1111 .iter()
1112 .map(|m| m.base_metrics.timing.mean_ns)
1113 .sum::<f64>();
1114 let sum_xy = metrics
1115 .iter()
1116 .map(|m| m.base_metrics.datasize as f64 * m.base_metrics.timing.mean_ns)
1117 .sum::<f64>();
1118 let sum_x2 = metrics
1119 .iter()
1120 .map(|m| (m.base_metrics.datasize as f64).powi(2))
1121 .sum::<f64>();
1122
1123 let slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x.powi(2));
1124 let intercept = (sum_y - slope * sum_x) / n;
1125
1126 let mean_y = sum_y / n;
1128 let ss_tot = metrics
1129 .iter()
1130 .map(|m| (m.base_metrics.timing.mean_ns - mean_y).powi(2))
1131 .sum::<f64>();
1132 let ss_res = metrics
1133 .iter()
1134 .map(|m| {
1135 let predicted = slope * m.base_metrics.datasize as f64 + intercept;
1136 (m.base_metrics.timing.mean_ns - predicted).powi(2)
1137 })
1138 .sum::<f64>();
1139 let r_squared = 1.0 - ss_res / ss_tot;
1140
1141 Ok(PerformanceModel {
1142 model_type: ModelType::Linear,
1143 coefficients: vec![intercept, slope],
1144 accuracy_metrics: ModelAccuracyMetrics {
1145 r_squared,
1146 mean_absolute_error: 0.0, root_mean_square_error: (ss_res / n).sqrt(),
1148 cross_validation_score: r_squared * 0.9, },
1150 feature_importance: [("datasize".to_string(), 1.0)].iter().cloned().collect(),
1151 })
1152 }
1153
1154 fn generate_intelligent_recommendations(
1156 &self,
1157 metrics: &[AdvancedBenchmarkMetrics],
1158 ) -> Vec<IntelligentRecommendation> {
1159 let mut recommendations = Vec::new();
1160
1161 recommendations.extend(self.analyze_simd_opportunities(metrics));
1163
1164 recommendations.extend(self.analyze_parallel_opportunities(metrics));
1166
1167 recommendations.extend(self.analyze_memory_opportunities(metrics));
1169
1170 recommendations.extend(self.analyze_stability_improvements(metrics));
1172
1173 recommendations
1174 }
1175
1176 fn analyze_simd_opportunities(
1178 &self,
1179 _metrics: &[AdvancedBenchmarkMetrics],
1180 ) -> Vec<IntelligentRecommendation> {
1181 vec![IntelligentRecommendation {
1182 category: RecommendationCategory::Performance,
1183 priority: RecommendationPriority::High,
1184 recommendation: "Enable SIMD optimizations for array operations".to_string(),
1185 expected_improvement: 2.5,
1186 confidence: 0.9,
1187 implementation_effort: ImplementationEffort::Low,
1188 compatibility_impact: CompatibilityImpact::None,
1189 platform_specificity: PlatformSpecificity::Universal,
1190 code_example: Some(
1191 r#"
1192// Enable SIMD for mean calculation
1193use scirs2_core::simd_ops::SimdUnifiedOps;
1194let result = f64::simd_mean(&data.view());
1195"#
1196 .to_string(),
1197 ),
1198 validation_strategy: "Compare SIMD vs scalar results for numerical accuracy"
1199 .to_string(),
1200 }]
1201 }
1202
1203 fn analyze_parallel_opportunities(
1205 &self,
1206 _metrics: &[AdvancedBenchmarkMetrics],
1207 ) -> Vec<IntelligentRecommendation> {
1208 vec![IntelligentRecommendation {
1209 category: RecommendationCategory::Performance,
1210 priority: RecommendationPriority::Medium,
1211 recommendation: "Use parallel processing for large datasets (>10K elements)"
1212 .to_string(),
1213 expected_improvement: 3.0,
1214 confidence: 0.8,
1215 implementation_effort: ImplementationEffort::Medium,
1216 compatibility_impact: CompatibilityImpact::Minor,
1217 platform_specificity: PlatformSpecificity::Universal,
1218 code_example: Some(
1219 r#"
1220// Enable parallel processing for large arrays
1221if data.len() > 10_000 {
1222 let result = parallel_mean(&data.view());
1223}
1224"#
1225 .to_string(),
1226 ),
1227 validation_strategy: "Verify thread safety and performance scaling".to_string(),
1228 }]
1229 }
1230
1231 fn analyze_memory_opportunities(
1233 &self,
1234 _metrics: &[AdvancedBenchmarkMetrics],
1235 ) -> Vec<IntelligentRecommendation> {
1236 vec![IntelligentRecommendation {
1237 category: RecommendationCategory::Memory,
1238 priority: RecommendationPriority::Medium,
1239 recommendation: "Use memory-mapped files for very large datasets".to_string(),
1240 expected_improvement: 1.5,
1241 confidence: 0.7,
1242 implementation_effort: ImplementationEffort::High,
1243 compatibility_impact: CompatibilityImpact::Moderate,
1244 platform_specificity: PlatformSpecificity::Family,
1245 code_example: None,
1246 validation_strategy: "Monitor memory usage and I/O patterns".to_string(),
1247 }]
1248 }
1249
1250 fn analyze_stability_improvements(
1252 &self,
1253 _metrics: &[AdvancedBenchmarkMetrics],
1254 ) -> Vec<IntelligentRecommendation> {
1255 vec![IntelligentRecommendation {
1256 category: RecommendationCategory::Stability,
1257 priority: RecommendationPriority::High,
1258 recommendation: "Use Kahan summation for improved numerical accuracy".to_string(),
1259 expected_improvement: 1.1,
1260 confidence: 0.95,
1261 implementation_effort: ImplementationEffort::Low,
1262 compatibility_impact: CompatibilityImpact::None,
1263 platform_specificity: PlatformSpecificity::Universal,
1264 code_example: Some(
1265 r#"
1266// Kahan summation for improved accuracy
1267#[allow(dead_code)]
1268fn kahan_sum(data: &[f64]) -> f64 {
1269 let mut sum = 0.0;
1270 let mut c = 0.0;
1271 for &value in data {
1272 let y = value - c;
1273 let t = sum + y;
1274 c = (t - sum) - y;
1275 sum = t;
1276 }
1277 sum
1278}
1279"#
1280 .to_string(),
1281 ),
1282 validation_strategy: "Compare with high-precision reference implementation".to_string(),
1283 }]
1284 }
1285
1286 fn create_comprehensive_analysis(
1288 &self,
1289 metrics: &[AdvancedBenchmarkMetrics],
1290 ) -> ComprehensiveAnalysis {
1291 ComprehensiveAnalysis {
1292 overall_performance_score: self.calculate_overall_score(metrics),
1293 scalability_assessment: self.assess_scalability(metrics),
1294 stability_assessment: self.assess_stability(metrics),
1295 cross_platform_assessment: self.assess_cross_platform(metrics),
1296 bottleneck_analysis: self.analyze_bottlenecks(metrics),
1297 optimization_opportunities: self.identify_optimization_opportunities(metrics),
1298 }
1299 }
1300
1301 fn calculate_overall_score(&self, metrics: &[AdvancedBenchmarkMetrics]) -> f64 {
1303 if metrics.is_empty() {
1304 return 0.0;
1305 }
1306
1307 let throughput_scores: Vec<f64> = metrics
1308 .iter()
1309 .map(|m| m.base_metrics.throughput / 1e6) .collect();
1311
1312 let mean_score = throughput_scores.iter().sum::<f64>() / throughput_scores.len() as f64;
1313
1314 (mean_score * 10.0).min(100.0)
1316 }
1317
1318 fn assess_scalability(&self, metrics: &[AdvancedBenchmarkMetrics]) -> ScalabilityAssessment {
1320 ScalabilityAssessment {
1321 scaling_efficiency: 0.85, memory_efficiency: 0.90,
1323 parallel_efficiency: 0.75,
1324 recommended_maxdatasize: 1_000_000,
1325 }
1326 }
1327
1328 fn assess_stability(&self, metrics: &[AdvancedBenchmarkMetrics]) -> StabilityAssessment {
1330 let avg_relative_error = metrics
1331 .iter()
1332 .map(|m| m.stability_metrics.relative_error)
1333 .sum::<f64>()
1334 / metrics.len() as f64;
1335
1336 StabilityAssessment {
1337 overall_stability_score: (1.0 - avg_relative_error).max(0.0),
1338 precision_loss_risk: if avg_relative_error > 1e-10 {
1339 StabilityRisk::Medium
1340 } else {
1341 StabilityRisk::Low
1342 },
1343 numerical_robustness: 0.95,
1344 }
1345 }
1346
1347 fn assess_cross_platform(
1349 &self,
1350 _metrics: &[AdvancedBenchmarkMetrics],
1351 ) -> CrossPlatformAssessment {
1352 CrossPlatformAssessment {
1353 portability_score: 0.9,
1354 performance_variance: 0.15,
1355 platform_compatibility: vec![
1356 ("x86_64".to_string(), 1.0),
1357 ("aarch64".to_string(), 0.85),
1358 ("wasm32".to_string(), 0.6),
1359 ],
1360 }
1361 }
1362
1363 fn analyze_bottlenecks(
1365 &self,
1366 _metrics: &[AdvancedBenchmarkMetrics],
1367 ) -> Vec<BottleneckAnalysis> {
1368 vec![
1369 BottleneckAnalysis {
1370 component: "Memory bandwidth".to_string(),
1371 impact_percentage: 35.0,
1372 mitigation_strategies: vec![
1373 "Use cache-friendly algorithms".to_string(),
1374 "Implement data prefetching".to_string(),
1375 ],
1376 },
1377 BottleneckAnalysis {
1378 component: "Computational complexity".to_string(),
1379 impact_percentage: 25.0,
1380 mitigation_strategies: vec![
1381 "Use more efficient algorithms".to_string(),
1382 "Enable SIMD optimizations".to_string(),
1383 ],
1384 },
1385 ]
1386 }
1387
1388 fn identify_optimization_opportunities(
1390 &self,
1391 _metrics: &[AdvancedBenchmarkMetrics],
1392 ) -> Vec<OptimizationOpportunity> {
1393 vec![
1394 OptimizationOpportunity {
1395 opportunity: "SIMD vectorization".to_string(),
1396 potential_improvement: 2.5,
1397 implementation_complexity: "Low".to_string(),
1398 risk_level: "Low".to_string(),
1399 },
1400 OptimizationOpportunity {
1401 opportunity: "Parallel processing".to_string(),
1402 potential_improvement: 3.0,
1403 implementation_complexity: "Medium".to_string(),
1404 risk_level: "Medium".to_string(),
1405 },
1406 ]
1407 }
1408}
1409
1410#[derive(Debug, Clone, Serialize, Deserialize)]
1412pub struct AdvancedBenchmarkReport {
1413 pub timestamp: String,
1414 pub config: AdvancedBenchmarkConfig,
1415 pub metrics: Vec<AdvancedBenchmarkMetrics>,
1416 pub analysis: ComprehensiveAnalysis,
1417 pub recommendations: Vec<IntelligentRecommendation>,
1418 pub performance_models: HashMap<String, PerformanceModel>,
1419 pub platform_profiles: HashMap<String, PlatformProfile>,
1420 pub execution_time: Duration,
1421}
1422
1423#[derive(Debug, Clone, Serialize, Deserialize)]
1425pub struct IntelligentRecommendation {
1426 pub category: RecommendationCategory,
1427 pub priority: RecommendationPriority,
1428 pub recommendation: String,
1429 pub expected_improvement: f64, pub confidence: f64, pub implementation_effort: ImplementationEffort,
1432 pub compatibility_impact: CompatibilityImpact,
1433 pub platform_specificity: PlatformSpecificity,
1434 pub code_example: Option<String>,
1435 pub validation_strategy: String,
1436}
1437
1438#[derive(Debug, Clone, Serialize, Deserialize)]
1440pub enum RecommendationCategory {
1441 Performance,
1442 Memory,
1443 Stability,
1444 Compatibility,
1445 Maintainability,
1446}
1447
1448#[derive(Debug, Clone, Serialize, Deserialize)]
1450pub enum RecommendationPriority {
1451 Critical,
1452 High,
1453 Medium,
1454 Low,
1455}
1456
1457#[derive(Debug, Clone, Serialize, Deserialize)]
1459pub enum ImplementationEffort {
1460 Trivial, Low, Medium, High, Expert, }
1466
1467#[derive(Debug, Clone, Serialize, Deserialize)]
1469pub struct ComprehensiveAnalysis {
1470 pub overall_performance_score: f64,
1471 pub scalability_assessment: ScalabilityAssessment,
1472 pub stability_assessment: StabilityAssessment,
1473 pub cross_platform_assessment: CrossPlatformAssessment,
1474 pub bottleneck_analysis: Vec<BottleneckAnalysis>,
1475 pub optimization_opportunities: Vec<OptimizationOpportunity>,
1476}
1477
1478#[derive(Debug, Clone, Serialize, Deserialize)]
1480pub struct ScalabilityAssessment {
1481 pub scaling_efficiency: f64,
1482 pub memory_efficiency: f64,
1483 pub parallel_efficiency: f64,
1484 pub recommended_maxdatasize: usize,
1485}
1486
1487#[derive(Debug, Clone, Serialize, Deserialize)]
1489pub struct StabilityAssessment {
1490 pub overall_stability_score: f64,
1491 pub precision_loss_risk: StabilityRisk,
1492 pub numerical_robustness: f64,
1493}
1494
1495#[derive(Debug, Clone, Serialize, Deserialize)]
1497pub enum StabilityRisk {
1498 Low,
1499 Medium,
1500 High,
1501 Critical,
1502}
1503
1504#[derive(Debug, Clone, Serialize, Deserialize)]
1506pub struct CrossPlatformAssessment {
1507 pub portability_score: f64,
1508 pub performance_variance: f64,
1509 pub platform_compatibility: Vec<(String, f64)>,
1510}
1511
1512#[derive(Debug, Clone, Serialize, Deserialize)]
1514pub struct BottleneckAnalysis {
1515 pub component: String,
1516 pub impact_percentage: f64,
1517 pub mitigation_strategies: Vec<String>,
1518}
1519
1520#[derive(Debug, Clone, Serialize, Deserialize)]
1522pub struct OptimizationOpportunity {
1523 pub opportunity: String,
1524 pub potential_improvement: f64,
1525 pub implementation_complexity: String,
1526 pub risk_level: String,
1527}
1528
1529impl Default for AdvancedBenchmarkConfig {
1530 fn default() -> Self {
1531 Self {
1532 base_config: BenchmarkConfig::default(),
1533 enable_predictive_modeling: true,
1534 enable_cross_platform: true,
1535 enable_stability_testing: true,
1536 enable_scalability_analysis: true,
1537 enable_complexity_analysis: true,
1538 enable_power_analysis: false, target_platforms: vec![TargetPlatform {
1540 name: "x86_64".to_string(),
1541 architecture: "x86_64".to_string(),
1542 cpu_features: vec!["AVX2".to_string(), "FMA".to_string()],
1543 memory_hierarchy: MemoryHierarchy {
1544 l1_cache_kb: 32,
1545 l2_cache_kb: 256,
1546 l3_cache_mb: 8,
1547 memory_bandwidth_gbps: 50.0,
1548 numa_nodes: 1,
1549 },
1550 expected_performance: Some(ExpectedPerformance {
1551 operations_per_second: 1e9,
1552 memory_bandwidth_utilization: 0.7,
1553 cache_efficiency: 0.8,
1554 }),
1555 }],
1556 data_distributions: vec![
1557 DataDistribution::Normal,
1558 DataDistribution::Uniform,
1559 DataDistribution::Sparse(0.9),
1560 ],
1561 precision_levels: vec![PrecisionLevel::Single, PrecisionLevel::Double],
1562 stress_test_configs: vec![StressTestConfig {
1563 name: "High memory pressure".to_string(),
1564 datasize_multiplier: 10.0,
1565 concurrent_operations: 4,
1566 memory_pressure: 0.8,
1567 thermal_stress: false,
1568 duration_minutes: 1.0,
1569 }],
1570 }
1571 }
1572}
1573
1574#[allow(dead_code)]
1576pub fn run_advanced_benchmarks(
1577 config: Option<AdvancedBenchmarkConfig>,
1578) -> StatsResult<AdvancedBenchmarkReport> {
1579 let config = config.unwrap_or_default();
1580 let mut suite = AdvancedBenchmarkSuite::new(config);
1581 suite.run_comprehensive_benchmarks()
1582}
1583
1584#[cfg(test)]
1585mod tests {
1586 use super::*;
1587
1588 #[test]
1589 fn test_advanced_benchmark_creation() {
1590 let config = AdvancedBenchmarkConfig::default();
1591 let suite = AdvancedBenchmarkSuite::new(config);
1592 assert!(suite.performance_models.is_empty());
1593 }
1594
1595 #[test]
1596 fn testdata_generation() {
1597 let config = AdvancedBenchmarkConfig::default();
1598 let suite = AdvancedBenchmarkSuite::new(config);
1599
1600 let data = suite
1601 .generate_testdata(100, &DataDistribution::Normal)
1602 .expect("Operation failed");
1603 assert_eq!(data.len(), 100);
1604
1605 let sparsedata = suite
1606 .generate_testdata(100, &DataDistribution::Sparse(0.9))
1607 .expect("Operation failed");
1608 let zero_count = sparsedata.iter().filter(|&&x| x == 0.0).count();
1609 assert!(zero_count > 50); }
1611
1612 #[test]
1613 fn test_performance_model_building() {
1614 let config = AdvancedBenchmarkConfig::default();
1615 let suite = AdvancedBenchmarkSuite::new(config);
1616
1617 let mock_metrics = vec![AdvancedBenchmarkMetrics {
1619 base_metrics: crate::benchmark_suite::BenchmarkMetrics {
1620 function_name: "test".to_string(),
1621 datasize: 100,
1622 timing: crate::benchmark_suite::TimingStats {
1623 mean_ns: 1000.0,
1624 std_dev_ns: 100.0,
1625 min_ns: 900.0,
1626 max_ns: 1200.0,
1627 median_ns: 1000.0,
1628 p95_ns: 1100.0,
1629 p99_ns: 1150.0,
1630 },
1631 memory: None,
1632 algorithm_config: crate::benchmark_suite::AlgorithmConfig {
1633 simd_enabled: false,
1634 parallel_enabled: false,
1635 thread_count: None,
1636 simd_width: None,
1637 algorithm_variant: "standard".to_string(),
1638 },
1639 throughput: 100000.0,
1640 baseline_comparison: None,
1641 },
1642 stability_metrics: NumericalStabilityMetrics {
1643 relative_error: 1e-15,
1644 condition_number: Some(1.0),
1645 error_accumulation_rate: 0.0,
1646 precision_loss_percent: 0.0,
1647 distribution_stability: HashMap::new(),
1648 },
1649 scalability_metrics: ScalabilityMetrics {
1650 complexity_class: ComplexityClass::Linear,
1651 measured_scaling_factor: 1.0,
1652 scale_efficiency: vec![(100, 1.0)],
1653 memory_scaling: MemoryScalingMetrics {
1654 allocation_efficiency: 0.95,
1655 memory_reuse_factor: 0.8,
1656 fragmentation_growth_rate: 0.01,
1657 cache_miss_rate_growth: 0.05,
1658 },
1659 parallel_scaling: None,
1660 },
1661 power_metrics: None,
1662 memory_hierarchy_metrics: MemoryHierarchyMetrics {
1663 l1_cache_hit_rate: 0.95,
1664 l2_cache_hit_rate: 0.85,
1665 l3_cache_hit_rate: 0.75,
1666 memory_bandwidth_utilization: 0.6,
1667 numa_locality_score: 0.9,
1668 prefetch_effectiveness: 0.7,
1669 },
1670 platform_variance: None,
1671 prediction_accuracy: None,
1672 }];
1673
1674 let model = suite
1675 .build_performance_model(&mock_metrics.iter().collect::<Vec<_>>())
1676 .expect("Operation failed");
1677 assert!(matches!(model.model_type, ModelType::Linear));
1678 assert_eq!(model.coefficients.len(), 2); }
1680
1681 fn fast_config(warmup_iterations: usize, iterations: usize) -> AdvancedBenchmarkConfig {
1684 let mut config = AdvancedBenchmarkConfig::default();
1685 config.base_config.warmup_iterations = warmup_iterations;
1686 config.base_config.iterations = iterations;
1687 config
1688 }
1689
1690 #[test]
1691 fn test_benchmark_stability_reports_real_timing() {
1692 let suite = AdvancedBenchmarkSuite::new(fast_config(2, 8));
1695 let data = Array1::from_elem(1000, 3.5_f64);
1696
1697 let metrics = suite
1698 .benchmark_stability("mean_stability_real", &data)
1699 .expect("stability benchmark should succeed with iterations > 0");
1700
1701 let timing = &metrics.base_metrics.timing;
1704 assert!(timing.mean_ns > 0.0, "measured mean must be positive");
1705 assert!(timing.mean_ns.is_finite());
1706 assert!(timing.min_ns <= timing.mean_ns);
1707 assert!(timing.mean_ns <= timing.max_ns);
1708 assert_eq!(metrics.base_metrics.function_name, "mean_stability_real");
1709 assert_eq!(metrics.base_metrics.datasize, 1000);
1710 }
1711
1712 #[test]
1713 fn test_benchmark_stability_honest_error_on_zero_iterations() {
1714 let suite = AdvancedBenchmarkSuite::new(fast_config(0, 0));
1717 let data = Array1::from_elem(100, 1.0_f64);
1718
1719 let err = suite
1720 .benchmark_stability("mean_stability_empty", &data)
1721 .expect_err("zero iterations must yield an honest error, not fake data");
1722 assert!(matches!(err, StatsError::InvalidArgument(_)));
1723 }
1724
1725 #[test]
1726 fn test_benchmark_cross_platform_reports_current_platform_only() {
1727 let suite = AdvancedBenchmarkSuite::new(fast_config(2, 8));
1731 let data = Array1::from_elem(1000, 2.0_f64);
1732
1733 let metrics = suite
1734 .benchmark_cross_platform("mean_cross_platform_real", &data)
1735 .expect("cross-platform benchmark should succeed with iterations > 0");
1736
1737 let variance = metrics
1738 .platform_variance
1739 .expect("platform variance must be present");
1740
1741 assert_eq!(variance.platform_specific_metrics.len(), 1);
1743 let arch = std::env::consts::ARCH;
1744 let measured = variance
1745 .platform_specific_metrics
1746 .get(arch)
1747 .copied()
1748 .expect("current architecture must be reported");
1749 assert!(measured > 0.0, "reported timing must be a real measurement");
1750
1751 assert!(variance.coefficient_of_variation >= 0.0);
1753 assert!(variance.coefficient_of_variation.is_finite());
1754
1755 assert!(variance
1757 .feature_dependency_analysis
1758 .simd_feature_impact
1759 .is_empty());
1760 }
1761
1762 #[test]
1763 fn test_benchmark_cross_platform_honest_error_on_zero_iterations() {
1764 let suite = AdvancedBenchmarkSuite::new(fast_config(0, 0));
1765 let data = Array1::from_elem(100, 1.0_f64);
1766
1767 let err = suite
1768 .benchmark_cross_platform("mean_cross_platform_empty", &data)
1769 .expect_err("zero iterations must yield an honest error, not fake data");
1770 assert!(matches!(err, StatsError::InvalidArgument(_)));
1771 }
1772}