Skip to main content

ferrous_forge/performance/
mod.rs

1//! Performance optimizations for Ferrous Forge
2//!
3//! This module provides performance enhancements including:
4//! - Parallel validation execution
5//! - Caching strategies
6//! - Lazy file parsing
7//! - Memory pooling
8
9pub mod cache;
10pub mod parallel;
11
12use std::sync::Arc;
13use std::time::Duration;
14
15/// Performance configuration
16#[derive(Debug, Clone)]
17pub struct PerformanceConfig {
18    /// Enable parallel execution
19    pub parallel_enabled: bool,
20    /// Number of worker threads (0 = auto)
21    pub thread_count: usize,
22    /// Enable caching
23    pub cache_enabled: bool,
24    /// Cache TTL in seconds
25    pub cache_ttl: Duration,
26    /// Enable lazy parsing
27    pub lazy_parsing: bool,
28    /// Memory pool size in MB
29    pub memory_pool_size: usize,
30}
31
32impl Default for PerformanceConfig {
33    fn default() -> Self {
34        Self {
35            parallel_enabled: true,
36            thread_count: 0, // Auto-detect
37            cache_enabled: true,
38            cache_ttl: Duration::from_secs(300), // 5 minutes
39            lazy_parsing: true,
40            memory_pool_size: 100, // 100MB
41        }
42    }
43}
44
45/// Performance metrics
46#[derive(Debug, Clone, Default)]
47pub struct PerformanceMetrics {
48    /// Total validation time in milliseconds
49    pub validation_time_ms: u64,
50    /// Memory usage in bytes
51    pub memory_usage_bytes: u64,
52    /// Number of files processed
53    pub files_processed: usize,
54    /// Cache hit rate (0.0 - 1.0)
55    pub cache_hit_rate: f64,
56    /// Parallel speedup factor
57    pub parallel_speedup: f64,
58}
59
60impl PerformanceMetrics {
61    /// Check if performance targets are met
62    pub fn meets_targets(&self) -> bool {
63        self.validation_time_ms < 2000 // < 2s
64            && self.memory_usage_bytes < 100 * 1024 * 1024 // < 100MB
65    }
66
67    /// Generate performance report
68    pub fn report(&self) -> String {
69        format!(
70            "Performance Metrics:\n\
71             - Validation time: {}ms\n\
72             - Memory usage: {:.2}MB\n\
73             - Files processed: {}\n\
74             - Cache hit rate: {:.1}%\n\
75             - Parallel speedup: {:.2}x",
76            self.validation_time_ms,
77            self.memory_usage_bytes as f64 / (1024.0 * 1024.0),
78            self.files_processed,
79            self.cache_hit_rate * 100.0,
80            self.parallel_speedup
81        )
82    }
83}
84
85/// Performance monitor
86pub struct PerformanceMonitor {
87    #[allow(dead_code)]
88    config: Arc<PerformanceConfig>,
89    metrics: Arc<dashmap::DashMap<String, PerformanceMetrics>>,
90}
91
92impl PerformanceMonitor {
93    /// Create a new performance monitor
94    pub fn new(config: PerformanceConfig) -> Self {
95        Self {
96            config: Arc::new(config),
97            metrics: Arc::new(dashmap::DashMap::new()),
98        }
99    }
100
101    /// Start monitoring a task
102    pub fn start_task(&self, task_name: &str) -> TaskMonitor {
103        TaskMonitor::new(task_name.to_string(), self.metrics.clone())
104    }
105
106    /// Get metrics for a task
107    pub fn get_metrics(&self, task_name: &str) -> Option<PerformanceMetrics> {
108        self.metrics.get(task_name).map(|m| m.clone())
109    }
110
111    /// Get all metrics
112    pub fn all_metrics(&self) -> Vec<(String, PerformanceMetrics)> {
113        self.metrics
114            .iter()
115            .map(|entry| (entry.key().clone(), entry.value().clone()))
116            .collect()
117    }
118}
119
120/// Task-specific performance monitor
121pub struct TaskMonitor {
122    task_name: String,
123    start_time: std::time::Instant,
124    metrics_map: Arc<dashmap::DashMap<String, PerformanceMetrics>>,
125}
126
127impl TaskMonitor {
128    fn new(
129        task_name: String,
130        metrics_map: Arc<dashmap::DashMap<String, PerformanceMetrics>>,
131    ) -> Self {
132        Self {
133            task_name,
134            start_time: std::time::Instant::now(),
135            metrics_map,
136        }
137    }
138
139    /// Complete the task and record metrics
140    pub fn complete(self, files_processed: usize) {
141        let elapsed = self.start_time.elapsed();
142        let metrics = PerformanceMetrics {
143            validation_time_ms: elapsed.as_millis() as u64,
144            memory_usage_bytes: estimate_memory_usage(),
145            files_processed,
146            cache_hit_rate: 0.0,   // Will be updated by cache module
147            parallel_speedup: 1.0, // Will be updated by parallel module
148        };
149        self.metrics_map.insert(self.task_name, metrics);
150    }
151}
152
153/// Estimate current memory usage
154fn estimate_memory_usage() -> u64 {
155    // This is a simplified estimation
156    // In production, we'd use more sophisticated memory tracking
157
158    // For now, use a simple heuristic based on thread count
159    let thread_count = rayon::current_num_threads();
160    let base_memory = 20 * 1024 * 1024; // 20MB base
161    let per_thread = 5 * 1024 * 1024; // 5MB per thread
162
163    base_memory + (thread_count as u64 * per_thread)
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169
170    #[test]
171    fn test_performance_config_default() {
172        let config = PerformanceConfig::default();
173        assert!(config.parallel_enabled);
174        assert!(config.cache_enabled);
175        assert_eq!(config.thread_count, 0);
176    }
177
178    #[test]
179    fn test_performance_metrics() {
180        let metrics = PerformanceMetrics {
181            validation_time_ms: 1500,
182            memory_usage_bytes: 50 * 1024 * 1024,
183            ..Default::default()
184        };
185
186        assert!(metrics.meets_targets());
187
188        let metrics = PerformanceMetrics {
189            validation_time_ms: 3000,
190            memory_usage_bytes: 50 * 1024 * 1024,
191            ..Default::default()
192        };
193        assert!(!metrics.meets_targets());
194    }
195
196    #[test]
197    fn test_performance_monitor() {
198        let config = PerformanceConfig::default();
199        let monitor = PerformanceMonitor::new(config);
200
201        let task = monitor.start_task("test_task");
202        task.complete(10);
203
204        let metrics = monitor.get_metrics("test_task");
205        assert!(metrics.is_some());
206    }
207}