scirs2_interpolate/advanced_coordinator_modules/
memory_management.rs

1//! Memory management and caching system for interpolation operations
2//!
3//! This module provides sophisticated memory management capabilities including
4//! memory tracking, adaptive caching, and performance monitoring to optimize
5//! interpolation operations for both memory usage and execution speed.
6
7use scirs2_core::numeric::Float;
8use std::collections::{HashMap, VecDeque};
9use std::fmt::Debug;
10use std::time::{Duration, Instant};
11
12use crate::advanced_coordinator_modules::types::{
13    DataProfile, InterpolationMethodType, PerformanceMetrics,
14};
15use crate::error::{InterpolateError, InterpolateResult};
16
17/// Memory management for interpolation
18#[derive(Debug)]
19pub struct InterpolationMemoryManager {
20    /// Memory usage tracking
21    memory_tracker: MemoryTracker,
22    /// Cache management
23    cache_manager: CacheManager,
24    /// Memory allocation strategy
25    allocation_strategy: MemoryAllocationStrategy,
26}
27
28impl InterpolationMemoryManager {
29    /// Create new memory manager
30    pub fn new() -> InterpolateResult<Self> {
31        Ok(Self {
32            memory_tracker: MemoryTracker::default(),
33            cache_manager: CacheManager::new()?,
34            allocation_strategy: MemoryAllocationStrategy::Adaptive,
35        })
36    }
37
38    /// Track memory usage for operation
39    pub fn track_memory_usage(&mut self, usage: usize, operation: String) -> InterpolateResult<()> {
40        self.memory_tracker.record_usage(usage, operation)?;
41
42        // Check if we need to adjust allocation strategy
43        if self.memory_tracker.should_adjust_strategy() {
44            self.adjust_allocation_strategy()?;
45        }
46
47        Ok(())
48    }
49
50    /// Get current memory usage
51    pub fn get_current_usage(&self) -> usize {
52        self.memory_tracker.current_usage
53    }
54
55    /// Get peak memory usage
56    pub fn get_peak_usage(&self) -> usize {
57        self.memory_tracker.peak_usage
58    }
59
60    /// Get memory usage statistics
61    pub fn get_memory_statistics(&self) -> MemoryStatistics {
62        MemoryStatistics {
63            current_usage: self.memory_tracker.current_usage,
64            peak_usage: self.memory_tracker.peak_usage,
65            average_usage: self.memory_tracker.calculate_average_usage(),
66            usage_trend: self.memory_tracker.calculate_usage_trend(),
67            allocation_strategy: self.allocation_strategy.clone(),
68        }
69    }
70
71    /// Optimize memory usage
72    pub fn optimize_memory_usage(&mut self) -> InterpolateResult<MemoryOptimizationResult> {
73        let initial_usage = self.memory_tracker.current_usage;
74
75        // Trigger cache cleanup
76        let cache_freed = self.cache_manager.cleanup_cache()?;
77
78        // Adjust allocation strategy if needed
79        self.adjust_allocation_strategy()?;
80
81        let final_usage = self.memory_tracker.current_usage;
82        let memory_freed = initial_usage.saturating_sub(final_usage);
83
84        Ok(MemoryOptimizationResult {
85            memory_freed: memory_freed + cache_freed,
86            cache_freed,
87            new_allocation_strategy: self.allocation_strategy.clone(),
88            optimization_effectiveness: if initial_usage > 0 {
89                memory_freed as f64 / initial_usage as f64
90            } else {
91                0.0
92            },
93        })
94    }
95
96    /// Set allocation strategy
97    pub fn set_allocation_strategy(&mut self, strategy: MemoryAllocationStrategy) {
98        self.allocation_strategy = strategy;
99    }
100
101    /// Adjust allocation strategy based on usage patterns
102    fn adjust_allocation_strategy(&mut self) -> InterpolateResult<()> {
103        let avg_usage = self.memory_tracker.calculate_average_usage();
104        let peak_usage = self.memory_tracker.peak_usage;
105
106        if peak_usage > 0 {
107            let usage_ratio = avg_usage as f64 / peak_usage as f64;
108
109            self.allocation_strategy = if usage_ratio > 0.8 {
110                MemoryAllocationStrategy::Aggressive // High consistent usage
111            } else if usage_ratio < 0.3 {
112                MemoryAllocationStrategy::Conservative // Low average usage
113            } else {
114                MemoryAllocationStrategy::Adaptive // Balanced usage
115            };
116        }
117
118        Ok(())
119    }
120}
121
122impl Default for InterpolationMemoryManager {
123    fn default() -> Self {
124        Self::new().unwrap_or_else(|_| Self {
125            memory_tracker: MemoryTracker::default(),
126            cache_manager: CacheManager::default(),
127            allocation_strategy: MemoryAllocationStrategy::Adaptive,
128        })
129    }
130}
131
132/// Memory usage tracking
133#[derive(Debug, Default)]
134pub struct MemoryTracker {
135    /// Current memory usage (bytes)
136    pub current_usage: usize,
137    /// Peak memory usage (bytes)
138    pub peak_usage: usize,
139    /// Memory usage history
140    pub usage_history: VecDeque<MemoryUsageRecord>,
141}
142
143impl MemoryTracker {
144    /// Record memory usage
145    pub fn record_usage(&mut self, usage: usize, operation: String) -> InterpolateResult<()> {
146        self.current_usage = usage;
147        if usage > self.peak_usage {
148            self.peak_usage = usage;
149        }
150
151        let record = MemoryUsageRecord {
152            usage,
153            timestamp: Instant::now(),
154            operation,
155        };
156
157        self.usage_history.push_back(record);
158
159        // Keep only last 1000 records
160        if self.usage_history.len() > 1000 {
161            self.usage_history.pop_front();
162        }
163
164        Ok(())
165    }
166
167    /// Calculate average memory usage
168    pub fn calculate_average_usage(&self) -> usize {
169        if self.usage_history.is_empty() {
170            return 0;
171        }
172
173        let sum: usize = self.usage_history.iter().map(|record| record.usage).sum();
174        sum / self.usage_history.len()
175    }
176
177    /// Calculate usage trend
178    pub fn calculate_usage_trend(&self) -> f64 {
179        if self.usage_history.len() < 2 {
180            return 0.0;
181        }
182
183        let recent_count = 10.min(self.usage_history.len());
184        let recent_usage: Vec<usize> = self
185            .usage_history
186            .iter()
187            .rev()
188            .take(recent_count)
189            .map(|record| record.usage)
190            .collect();
191
192        if recent_usage.len() < 2 {
193            return 0.0;
194        }
195
196        let first_half = &recent_usage[recent_usage.len() / 2..];
197        let second_half = &recent_usage[..recent_usage.len() / 2];
198
199        let first_avg = first_half.iter().sum::<usize>() as f64 / first_half.len() as f64;
200        let second_avg = second_half.iter().sum::<usize>() as f64 / second_half.len() as f64;
201
202        if first_avg > 0.0 {
203            (second_avg - first_avg) / first_avg
204        } else {
205            0.0
206        }
207    }
208
209    /// Check if allocation strategy should be adjusted
210    pub fn should_adjust_strategy(&self) -> bool {
211        self.usage_history.len() >= 10 && self.usage_history.len().is_multiple_of(50)
212        // Check every 50 records
213    }
214}
215
216/// Memory usage record
217#[derive(Debug, Clone)]
218pub struct MemoryUsageRecord {
219    /// Memory usage (bytes)
220    pub usage: usize,
221    /// Timestamp
222    pub timestamp: Instant,
223    /// Operation type that caused the usage
224    pub operation: String,
225}
226
227/// Cache management system
228#[derive(Debug)]
229pub struct CacheManager {
230    /// Cache hit ratio
231    hit_ratio: f64,
232    /// Cache size (bytes)
233    cache_size: usize,
234    /// Eviction policy
235    eviction_policy: CacheEvictionPolicy,
236    /// Cache statistics
237    statistics: CacheStatistics,
238}
239
240impl CacheManager {
241    /// Create new cache manager
242    pub fn new() -> InterpolateResult<Self> {
243        Ok(Self {
244            hit_ratio: 0.0,
245            cache_size: 0,
246            eviction_policy: CacheEvictionPolicy::Adaptive,
247            statistics: CacheStatistics::default(),
248        })
249    }
250
251    /// Record cache hit
252    pub fn record_hit(&mut self) {
253        self.statistics.hit_count += 1;
254        self.update_hit_ratio();
255    }
256
257    /// Record cache miss
258    pub fn record_miss(&mut self) {
259        self.statistics.miss_count += 1;
260        self.update_hit_ratio();
261    }
262
263    /// Record cache eviction
264    pub fn record_eviction(&mut self, freed_bytes: usize) {
265        self.statistics.eviction_count += 1;
266        self.cache_size = self.cache_size.saturating_sub(freed_bytes);
267        self.statistics.total_cache_size = self.cache_size;
268    }
269
270    /// Update cache size
271    pub fn update_cache_size(&mut self, new_size: usize) {
272        self.cache_size = new_size;
273        self.statistics.total_cache_size = new_size;
274    }
275
276    /// Get cache statistics
277    pub fn get_statistics(&self) -> &CacheStatistics {
278        &self.statistics
279    }
280
281    /// Get hit ratio
282    pub fn get_hit_ratio(&self) -> f64 {
283        self.hit_ratio
284    }
285
286    /// Cleanup cache
287    pub fn cleanup_cache(&mut self) -> InterpolateResult<usize> {
288        let initial_size = self.cache_size;
289
290        // Simulate cache cleanup based on eviction policy
291        let cleanup_percentage = match self.eviction_policy {
292            CacheEvictionPolicy::LRU => 0.3,
293            CacheEvictionPolicy::LFU => 0.25,
294            CacheEvictionPolicy::TimeBasedExpiration { .. } => 0.4,
295            CacheEvictionPolicy::SizeBasedEviction { .. } => 0.5,
296            CacheEvictionPolicy::Adaptive => {
297                if self.hit_ratio < 0.3 {
298                    0.6 // Aggressive cleanup for poor hit ratio
299                } else if self.hit_ratio < 0.7 {
300                    0.3 // Moderate cleanup
301                } else {
302                    0.1 // Conservative cleanup for good hit ratio
303                }
304            }
305        };
306
307        let bytes_freed = (self.cache_size as f64 * cleanup_percentage) as usize;
308        self.cache_size = self.cache_size.saturating_sub(bytes_freed);
309        self.statistics.total_cache_size = self.cache_size;
310        self.statistics.eviction_count += 1;
311
312        Ok(bytes_freed)
313    }
314
315    /// Update hit ratio
316    fn update_hit_ratio(&mut self) {
317        let total_requests = self.statistics.hit_count + self.statistics.miss_count;
318        if total_requests > 0 {
319            self.hit_ratio = self.statistics.hit_count as f64 / total_requests as f64;
320        }
321    }
322}
323
324impl Default for CacheManager {
325    fn default() -> Self {
326        Self::new().unwrap_or_else(|_| Self {
327            hit_ratio: 0.0,
328            cache_size: 0,
329            eviction_policy: CacheEvictionPolicy::Adaptive,
330            statistics: CacheStatistics::default(),
331        })
332    }
333}
334
335/// Cache eviction policy
336#[derive(Debug, Clone)]
337pub enum CacheEvictionPolicy {
338    /// Least Recently Used
339    LRU,
340    /// Least Frequently Used
341    LFU,
342    /// Time-based expiration
343    TimeBasedExpiration { ttl: Duration },
344    /// Size-based eviction
345    SizeBasedEviction { max_size: usize },
346    /// Adaptive policy
347    Adaptive,
348}
349
350/// Memory allocation strategy
351#[derive(Debug, Clone)]
352pub enum MemoryAllocationStrategy {
353    /// Conservative allocation
354    Conservative,
355    /// Aggressive pre-allocation
356    Aggressive,
357    /// Adaptive based on usage patterns
358    Adaptive,
359    /// Custom allocation strategy
360    Custom { strategy: String },
361}
362
363/// Performance tracking for interpolation
364#[derive(Debug, Default)]
365pub struct InterpolationPerformanceTracker {
366    /// Execution time history
367    pub execution_times: VecDeque<f64>,
368    /// Memory usage history
369    pub memory_usage: VecDeque<usize>,
370    /// Accuracy measurements
371    pub accuracy_measurements: VecDeque<f64>,
372    /// Method usage statistics
373    pub method_usage: HashMap<InterpolationMethodType, MethodStats>,
374    /// Performance trends
375    pub performance_trends: PerformanceTrends,
376}
377
378impl InterpolationPerformanceTracker {
379    /// Track performance for method
380    pub fn track_performance(
381        &mut self,
382        method: InterpolationMethodType,
383        performance: &PerformanceMetrics,
384    ) -> InterpolateResult<()> {
385        // Update execution times
386        self.execution_times
387            .push_back(performance.execution_time_ms);
388        if self.execution_times.len() > 1000 {
389            self.execution_times.pop_front();
390        }
391
392        // Update memory usage
393        self.memory_usage.push_back(performance.memory_usage_bytes);
394        if self.memory_usage.len() > 1000 {
395            self.memory_usage.pop_front();
396        }
397
398        // Update accuracy measurements
399        self.accuracy_measurements.push_back(performance.accuracy);
400        if self.accuracy_measurements.len() > 1000 {
401            self.accuracy_measurements.pop_front();
402        }
403
404        // Update method statistics
405        let stats = self.method_usage.entry(method).or_default();
406        stats.update_with_performance(performance);
407
408        // Update trends
409        self.update_performance_trends()?;
410
411        Ok(())
412    }
413
414    /// Get performance summary
415    pub fn get_performance_summary(&self) -> PerformanceSummary {
416        PerformanceSummary {
417            average_execution_time: self.calculate_average_execution_time(),
418            average_memory_usage: self.calculate_average_memory_usage(),
419            average_accuracy: self.calculate_average_accuracy(),
420            best_performing_method: self.get_best_performing_method(),
421            performance_trends: self.performance_trends.clone(),
422        }
423    }
424
425    /// Calculate average execution time
426    fn calculate_average_execution_time(&self) -> f64 {
427        if self.execution_times.is_empty() {
428            return 0.0;
429        }
430        self.execution_times.iter().sum::<f64>() / self.execution_times.len() as f64
431    }
432
433    /// Calculate average memory usage
434    fn calculate_average_memory_usage(&self) -> usize {
435        if self.memory_usage.is_empty() {
436            return 0;
437        }
438        self.memory_usage.iter().sum::<usize>() / self.memory_usage.len()
439    }
440
441    /// Calculate average accuracy
442    fn calculate_average_accuracy(&self) -> f64 {
443        if self.accuracy_measurements.is_empty() {
444            return 0.0;
445        }
446        self.accuracy_measurements.iter().sum::<f64>() / self.accuracy_measurements.len() as f64
447    }
448
449    /// Get best performing method
450    fn get_best_performing_method(&self) -> Option<InterpolationMethodType> {
451        self.method_usage
452            .iter()
453            .max_by(|a, b| {
454                let score_a = a.1.calculate_performance_score();
455                let score_b = b.1.calculate_performance_score();
456                score_a
457                    .partial_cmp(&score_b)
458                    .unwrap_or(std::cmp::Ordering::Equal)
459            })
460            .map(|(method, _)| *method)
461    }
462
463    /// Update performance trends
464    fn update_performance_trends(&mut self) -> InterpolateResult<()> {
465        self.performance_trends.execution_time_trend = self.calculate_trend(&self.execution_times);
466        self.performance_trends.memory_usage_trend = self.calculate_usage_trend(&self.memory_usage);
467        self.performance_trends.accuracy_trend = self.calculate_trend(&self.accuracy_measurements);
468
469        // Calculate overall performance score
470        self.performance_trends.overall_performance_score =
471            (self.performance_trends.accuracy_trend * 0.5)
472                + (-self.performance_trends.execution_time_trend * 0.3)
473                + (-self.performance_trends.memory_usage_trend * 0.2);
474
475        Ok(())
476    }
477
478    /// Calculate trend for f64 values
479    fn calculate_trend(&self, values: &VecDeque<f64>) -> f64 {
480        if values.len() < 10 {
481            return 0.0;
482        }
483
484        let recent_count = 10.min(values.len());
485        let recent_values: Vec<f64> = values.iter().rev().take(recent_count).copied().collect();
486
487        let mid_point = recent_values.len() / 2;
488        let first_half = &recent_values[mid_point..];
489        let second_half = &recent_values[..mid_point];
490
491        let first_avg = first_half.iter().sum::<f64>() / first_half.len() as f64;
492        let second_avg = second_half.iter().sum::<f64>() / second_half.len() as f64;
493
494        if first_avg != 0.0 {
495            (second_avg - first_avg) / first_avg
496        } else {
497            0.0
498        }
499    }
500
501    /// Calculate trend for usize values
502    fn calculate_usage_trend(&self, values: &VecDeque<usize>) -> f64 {
503        if values.len() < 10 {
504            return 0.0;
505        }
506
507        let recent_count = 10.min(values.len());
508        let recent_values: Vec<usize> = values.iter().rev().take(recent_count).copied().collect();
509
510        let mid_point = recent_values.len() / 2;
511        let first_half = &recent_values[mid_point..];
512        let second_half = &recent_values[..mid_point];
513
514        let first_avg = first_half.iter().sum::<usize>() as f64 / first_half.len() as f64;
515        let second_avg = second_half.iter().sum::<usize>() as f64 / second_half.len() as f64;
516
517        if first_avg != 0.0 {
518            (second_avg - first_avg) / first_avg
519        } else {
520            0.0
521        }
522    }
523}
524
525/// Method usage statistics
526#[derive(Debug, Clone, Default)]
527pub struct MethodStats {
528    /// Usage count
529    pub usage_count: usize,
530    /// Average execution time
531    pub avg_execution_time: f64,
532    /// Average memory usage
533    pub avg_memory_usage: usize,
534    /// Average accuracy
535    pub avg_accuracy: f64,
536    /// Success rate
537    pub success_rate: f64,
538    /// Total executions
539    total_executions: usize,
540    /// Successful executions
541    successful_executions: usize,
542}
543
544impl MethodStats {
545    /// Update statistics with performance data
546    pub fn update_with_performance(&mut self, performance: &PerformanceMetrics) {
547        self.usage_count += 1;
548        self.total_executions += 1;
549
550        if performance.accuracy > 0.7 {
551            self.successful_executions += 1;
552        }
553
554        // Update running averages
555        let count = self.usage_count as f64;
556        self.avg_execution_time =
557            (self.avg_execution_time * (count - 1.0) + performance.execution_time_ms) / count;
558        self.avg_memory_usage = ((self.avg_memory_usage as f64 * (count - 1.0))
559            + performance.memory_usage_bytes as f64) as usize
560            / self.usage_count;
561        self.avg_accuracy = (self.avg_accuracy * (count - 1.0) + performance.accuracy) / count;
562
563        // Update success rate
564        self.success_rate = self.successful_executions as f64 / self.total_executions as f64;
565    }
566
567    /// Calculate overall performance score
568    pub fn calculate_performance_score(&self) -> f64 {
569        if self.usage_count == 0 {
570            return 0.0;
571        }
572
573        // Weighted score: accuracy (50%), success rate (30%), efficiency (20%)
574        let efficiency_score = if self.avg_execution_time > 0.0 {
575            1.0 / (1.0 + self.avg_execution_time / 1000.0) // Normalize execution time
576        } else {
577            1.0
578        };
579
580        self.avg_accuracy * 0.5 + self.success_rate * 0.3 + efficiency_score * 0.2
581    }
582}
583
584/// Performance trends
585#[derive(Debug, Default, Clone)]
586pub struct PerformanceTrends {
587    /// Execution time trend (positive = getting slower)
588    pub execution_time_trend: f64,
589    /// Memory usage trend (positive = using more memory)
590    pub memory_usage_trend: f64,
591    /// Accuracy trend (positive = getting more accurate)
592    pub accuracy_trend: f64,
593    /// Overall performance score
594    pub overall_performance_score: f64,
595}
596
597/// Adaptive interpolation cache system
598#[derive(Debug)]
599pub struct AdaptiveInterpolationCache<F: Float + Debug> {
600    /// Cached interpolants
601    interpolant_cache: HashMap<InterpolantCacheKey, CachedInterpolant<F>>,
602    /// Cache statistics
603    cache_stats: CacheStatistics,
604    /// Cache policy
605    cache_policy: AdaptiveCachePolicy,
606}
607
608impl<F: Float + Debug> AdaptiveInterpolationCache<F> {
609    /// Create new adaptive cache
610    pub fn new() -> InterpolateResult<Self> {
611        Ok(Self {
612            interpolant_cache: HashMap::new(),
613            cache_stats: CacheStatistics::default(),
614            cache_policy: AdaptiveCachePolicy::new(),
615        })
616    }
617
618    /// Get cached interpolant
619    pub fn get(&mut self, key: &InterpolantCacheKey) -> Option<&CachedInterpolant<F>> {
620        if let Some(interpolant) = self.interpolant_cache.get_mut(key) {
621            interpolant.access_count += 1;
622            interpolant.last_access = Instant::now();
623            self.cache_stats.hit_count += 1;
624            Some(interpolant)
625        } else {
626            self.cache_stats.miss_count += 1;
627            None
628        }
629    }
630
631    /// Store interpolant in cache
632    pub fn store(
633        &mut self,
634        key: InterpolantCacheKey,
635        interpolant: CachedInterpolant<F>,
636    ) -> InterpolateResult<()> {
637        // Check if we need to evict
638        if self.should_evict() {
639            self.evict_entries()?;
640        }
641
642        let interpolant_size = interpolant.interpolant_data.len();
643        self.interpolant_cache.insert(key, interpolant);
644        self.cache_stats.total_cache_size += interpolant_size;
645
646        Ok(())
647    }
648
649    /// Clear cache
650    pub fn clear(&mut self) {
651        self.interpolant_cache.clear();
652        self.cache_stats.total_cache_size = 0;
653        self.cache_stats.eviction_count += 1;
654    }
655
656    /// Get cache statistics
657    pub fn get_statistics(&self) -> &CacheStatistics {
658        &self.cache_stats
659    }
660
661    /// Check if eviction is needed
662    fn should_evict(&self) -> bool {
663        match &self.cache_policy.base_policy {
664            CacheEvictionPolicy::SizeBasedEviction { max_size } => {
665                self.cache_stats.total_cache_size > *max_size
666            }
667            _ => self.interpolant_cache.len() > 1000, // Default size limit
668        }
669    }
670
671    /// Evict cache entries
672    fn evict_entries(&mut self) -> InterpolateResult<()> {
673        match &self.cache_policy.base_policy {
674            CacheEvictionPolicy::LRU => {
675                self.evict_lru();
676            }
677            CacheEvictionPolicy::LFU => {
678                self.evict_lfu();
679            }
680            CacheEvictionPolicy::TimeBasedExpiration { ttl } => {
681                self.evict_expired(*ttl);
682            }
683            _ => {
684                self.evict_lru(); // Default to LRU
685            }
686        }
687
688        self.cache_stats.eviction_count += 1;
689        Ok(())
690    }
691
692    /// Evict least recently used entries
693    fn evict_lru(&mut self) {
694        if let Some((key_to_remove, size)) = self
695            .interpolant_cache
696            .iter()
697            .min_by_key(|(_, interpolant)| interpolant.last_access)
698            .map(|(key, interpolant)| (key.clone(), interpolant.interpolant_data.len()))
699        {
700            self.interpolant_cache.remove(&key_to_remove);
701            self.cache_stats.total_cache_size =
702                self.cache_stats.total_cache_size.saturating_sub(size);
703        }
704    }
705
706    /// Evict least frequently used entries
707    fn evict_lfu(&mut self) {
708        if let Some((key_to_remove, size)) = self
709            .interpolant_cache
710            .iter()
711            .min_by_key(|(_, interpolant)| interpolant.access_count)
712            .map(|(key, interpolant)| (key.clone(), interpolant.interpolant_data.len()))
713        {
714            self.interpolant_cache.remove(&key_to_remove);
715            self.cache_stats.total_cache_size =
716                self.cache_stats.total_cache_size.saturating_sub(size);
717        }
718    }
719
720    /// Evict expired entries
721    fn evict_expired(&mut self, ttl: Duration) {
722        let now = Instant::now();
723        let mut keys_to_remove = Vec::new();
724        let mut total_size_removed = 0;
725
726        for (key, interpolant) in &self.interpolant_cache {
727            if now.duration_since(interpolant.creation_time) > ttl {
728                keys_to_remove.push(key.clone());
729                total_size_removed += interpolant.interpolant_data.len();
730            }
731        }
732
733        for key in keys_to_remove {
734            self.interpolant_cache.remove(&key);
735        }
736
737        self.cache_stats.total_cache_size = self
738            .cache_stats
739            .total_cache_size
740            .saturating_sub(total_size_removed);
741    }
742}
743
744impl<F: Float + Debug> Default for AdaptiveInterpolationCache<F> {
745    fn default() -> Self {
746        Self::new().unwrap_or_else(|_| Self {
747            interpolant_cache: HashMap::new(),
748            cache_stats: CacheStatistics::default(),
749            cache_policy: AdaptiveCachePolicy::default(),
750        })
751    }
752}
753
754/// Key for interpolant cache
755#[derive(Debug, Clone, Hash, Eq, PartialEq)]
756pub struct InterpolantCacheKey {
757    /// Data signature (hash of input data)
758    pub data_signature: String,
759    /// Method used
760    pub method: InterpolationMethodType,
761    /// Parameters used
762    pub parameters: String, // Serialized parameters
763}
764
765/// Cached interpolant
766#[derive(Debug, Clone)]
767pub struct CachedInterpolant<F: Float> {
768    /// Interpolant data
769    pub interpolant_data: Vec<u8>,
770    /// Creation time
771    pub creation_time: Instant,
772    /// Access count
773    pub access_count: usize,
774    /// Last access time
775    pub last_access: Instant,
776    /// Performance metrics
777    pub performance_metrics: CachedInterpolantMetrics<F>,
778}
779
780/// Performance metrics for cached interpolants
781#[derive(Debug, Clone)]
782pub struct CachedInterpolantMetrics<F: Float> {
783    /// Creation time
784    pub creation_time: F,
785    /// Memory usage
786    pub memory_usage: usize,
787    /// Accuracy score
788    pub accuracy_score: F,
789}
790
791/// Cache statistics
792#[derive(Debug, Default)]
793pub struct CacheStatistics {
794    /// Cache hit count
795    pub hit_count: usize,
796    /// Cache miss count
797    pub miss_count: usize,
798    /// Cache eviction count
799    pub eviction_count: usize,
800    /// Total cache size (bytes)
801    pub total_cache_size: usize,
802}
803
804impl CacheStatistics {
805    /// Calculate hit ratio
806    pub fn hit_ratio(&self) -> f64 {
807        let total = self.hit_count + self.miss_count;
808        if total > 0 {
809            self.hit_count as f64 / total as f64
810        } else {
811            0.0
812        }
813    }
814}
815
816/// Adaptive cache policy
817#[derive(Debug)]
818pub struct AdaptiveCachePolicy {
819    /// Base eviction policy
820    base_policy: CacheEvictionPolicy,
821    /// Adaptive parameters
822    adaptive_params: CacheAdaptiveParams,
823}
824
825impl AdaptiveCachePolicy {
826    /// Create new adaptive cache policy
827    pub fn new() -> Self {
828        Self {
829            base_policy: CacheEvictionPolicy::LRU,
830            adaptive_params: CacheAdaptiveParams::default(),
831        }
832    }
833
834    /// Adapt policy based on statistics
835    pub fn adapt_policy(&mut self, stats: &CacheStatistics) {
836        let hit_ratio = stats.hit_ratio();
837
838        if hit_ratio < self.adaptive_params.hit_ratio_threshold {
839            // Poor hit ratio - try different policy
840            self.base_policy = match &self.base_policy {
841                CacheEvictionPolicy::LRU => CacheEvictionPolicy::LFU,
842                CacheEvictionPolicy::LFU => CacheEvictionPolicy::TimeBasedExpiration {
843                    ttl: Duration::from_secs(300),
844                },
845                _ => CacheEvictionPolicy::LRU,
846            };
847        }
848    }
849}
850
851impl Default for AdaptiveCachePolicy {
852    fn default() -> Self {
853        Self::new()
854    }
855}
856
857/// Adaptive parameters for cache
858#[derive(Debug, Clone)]
859pub struct CacheAdaptiveParams {
860    /// Hit ratio threshold for policy adaptation
861    pub hit_ratio_threshold: f64,
862    /// Memory pressure threshold
863    pub memory_pressure_threshold: f64,
864    /// Access pattern weight
865    pub access_pattern_weight: f64,
866    /// Temporal locality weight
867    pub temporal_locality_weight: f64,
868}
869
870impl Default for CacheAdaptiveParams {
871    fn default() -> Self {
872        Self {
873            hit_ratio_threshold: 0.7,
874            memory_pressure_threshold: 0.8,
875            access_pattern_weight: 0.6,
876            temporal_locality_weight: 0.4,
877        }
878    }
879}
880
881/// Memory statistics
882#[derive(Debug, Clone)]
883pub struct MemoryStatistics {
884    /// Current memory usage
885    pub current_usage: usize,
886    /// Peak memory usage
887    pub peak_usage: usize,
888    /// Average memory usage
889    pub average_usage: usize,
890    /// Usage trend
891    pub usage_trend: f64,
892    /// Current allocation strategy
893    pub allocation_strategy: MemoryAllocationStrategy,
894}
895
896/// Memory optimization result
897#[derive(Debug, Clone)]
898pub struct MemoryOptimizationResult {
899    /// Memory freed (bytes)
900    pub memory_freed: usize,
901    /// Memory freed from cache (bytes)
902    pub cache_freed: usize,
903    /// New allocation strategy
904    pub new_allocation_strategy: MemoryAllocationStrategy,
905    /// Optimization effectiveness (0.0 to 1.0)
906    pub optimization_effectiveness: f64,
907}
908
909/// Performance summary
910#[derive(Debug, Clone)]
911pub struct PerformanceSummary {
912    /// Average execution time
913    pub average_execution_time: f64,
914    /// Average memory usage
915    pub average_memory_usage: usize,
916    /// Average accuracy
917    pub average_accuracy: f64,
918    /// Best performing method
919    pub best_performing_method: Option<InterpolationMethodType>,
920    /// Performance trends
921    pub performance_trends: PerformanceTrends,
922}