use scirs2_core::metrics::MetricsRegistry;
use std::sync::RwLock;
use std::time::Duration;
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
pub struct StatsConfig {
pub enable_simd: bool,
pub simd_threshold: usize,
pub enable_parallel: bool,
pub parallel_threshold: usize,
pub num_threads: usize,
pub enable_memory_efficient: bool,
pub memory_mapping_threshold: usize,
pub enable_adaptive_chunking: bool,
pub adaptive_chunk_size: usize,
pub enable_numerical_stability: bool,
pub enable_performance_monitoring: bool,
pub enable_cache_optimization: bool,
pub target_precision: f64,
}
impl Default for StatsConfig {
fn default() -> Self {
Self {
enable_simd: true,
simd_threshold: 1024,
enable_parallel: true,
parallel_threshold: 100_000,
num_threads: 0, enable_memory_efficient: true,
memory_mapping_threshold: 100 * 1024 * 1024, enable_adaptive_chunking: true,
adaptive_chunk_size: 64 * 1024, enable_numerical_stability: true,
enable_performance_monitoring: true,
enable_cache_optimization: true,
target_precision: 1e-12,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct StatisticalMetrics {
pub operation: String,
pub input_size: usize,
pub computation_time: Duration,
pub memory_usage: usize,
pub simd_utilization: f64,
pub parallel_efficiency: f64,
pub cache_hit_rate: f64,
pub numerical_error: f64,
pub performance_score: f64,
}
lazy_static::lazy_static! {
pub(super) static ref STATS_CONFIG: RwLock<StatsConfig> = RwLock::new(StatsConfig::default());
pub(super) static ref PERFORMANCE_METRICS: RwLock<Vec<StatisticalMetrics>> = RwLock::new(Vec::new());
pub(super) static ref METRICS_REGISTRY: MetricsRegistry = MetricsRegistry::new();
}
pub fn get_stats_config() -> StatsConfig {
STATS_CONFIG
.read()
.expect("read lock should not be poisoned")
.clone()
}
pub fn set_stats_config(config: StatsConfig) {
if let Ok(mut global_config) = STATS_CONFIG.write() {
*global_config = config;
}
}
pub fn get_performance_metrics() -> Vec<StatisticalMetrics> {
PERFORMANCE_METRICS
.read()
.expect("read lock should not be poisoned")
.clone()
}
pub fn clear_performance_metrics() {
if let Ok(mut metrics) = PERFORMANCE_METRICS.write() {
metrics.clear();
}
}
pub fn generate_performance_report() -> String {
let metrics = get_performance_metrics();
if metrics.is_empty() {
return "No performance metrics available".to_string();
}
let total_ops = metrics.len();
let avg_time = metrics
.iter()
.map(|m| m.computation_time.as_secs_f64())
.sum::<f64>()
/ total_ops as f64;
let avg_perf_score =
metrics.iter().map(|m| m.performance_score).sum::<f64>() / total_ops as f64;
format!(
"Statistical Operations Performance Report\n\
==========================================\n\
Total Operations: {}\n\
Average Computation Time: {:.3}ms\n\
Average Performance Score: {:.2} ops/sec\n\
SIMD Utilization: {:.1}%\n\
Parallel Efficiency: {:.1}%\n",
total_ops,
avg_time * 1000.0,
avg_perf_score,
metrics.iter().map(|m| m.simd_utilization).sum::<f64>() / total_ops as f64 * 100.0,
metrics.iter().map(|m| m.parallel_efficiency).sum::<f64>() / total_ops as f64 * 100.0,
)
}
pub(super) fn record_stats_metrics(
operation: &str,
input_size: usize,
computation_time: Duration,
simd_utilization: f64,
parallel_efficiency: f64,
) {
let metrics = StatisticalMetrics {
operation: operation.to_string(),
input_size,
computation_time,
memory_usage: input_size * std::mem::size_of::<f64>(), simd_utilization,
parallel_efficiency,
cache_hit_rate: 0.0, numerical_error: 0.0, performance_score: input_size as f64 / computation_time.as_secs_f64(),
};
if let Ok(mut metrics_vec) = PERFORMANCE_METRICS.write() {
metrics_vec.push(metrics);
if metrics_vec.len() > 1000 {
metrics_vec.drain(0..500);
}
}
}