1use crate::tools::tree_sitter::CodeAnalysis;
10use anyhow::Result;
11use serde::{Deserialize, Serialize};
12use std::collections::{HashMap, VecDeque};
13use std::path::{Path, PathBuf};
14use std::sync::Arc;
15use std::time::{Duration, Instant};
16use tokio::sync::RwLock;
17
18pub struct IntelligentCache<T> {
20 cache: Arc<RwLock<HashMap<String, CacheEntry<T>>>>,
21 access_order: Arc<RwLock<VecDeque<String>>>,
22 max_size: usize,
23 ttl: Duration,
24}
25
26#[derive(Debug, Clone)]
27struct CacheEntry<T> {
28 data: T,
29 timestamp: Instant,
30 access_count: usize,
31 size_estimate: usize,
32}
33
34impl<T> IntelligentCache<T> {
35 pub fn new(max_size: usize, ttl: Duration) -> Self {
36 Self {
37 cache: Arc::new(RwLock::new(HashMap::new())),
38 access_order: Arc::new(RwLock::new(VecDeque::new())),
39 max_size,
40 ttl,
41 }
42 }
43
44 pub async fn get(&self, key: &str) -> Option<T>
45 where
46 T: Clone,
47 {
48 let mut cache = self.cache.write().await;
49 let mut access_order = self.access_order.write().await;
50
51 if let Some(entry) = cache.get_mut(key) {
52 if entry.timestamp.elapsed() > self.ttl {
54 cache.remove(key);
55 access_order.retain(|k| k != key);
56 return None;
57 }
58
59 entry.access_count += 1;
61
62 access_order.retain(|k| k != key);
64 access_order.push_front(key.to_string());
65
66 Some(entry.data.clone())
67 } else {
68 None
69 }
70 }
71
72 pub async fn put(&self, key: String, value: T, size_estimate: usize) {
73 let mut cache = self.cache.write().await;
74 let mut access_order = self.access_order.write().await;
75
76 if cache.contains_key(&key) {
78 cache.remove(&key);
79 access_order.retain(|k| k != &key);
80 }
81
82 while cache.len() >= self.max_size {
84 if let Some(evict_key) = access_order.pop_back() {
85 cache.remove(&evict_key);
86 }
87 }
88
89 let entry = CacheEntry {
91 data: value,
92 timestamp: Instant::now(),
93 access_count: 1,
94 size_estimate,
95 };
96
97 cache.insert(key.clone(), entry);
98 access_order.push_front(key);
99 }
100
101 pub async fn clear(&self) {
102 let mut cache = self.cache.write().await;
103 let mut access_order = self.access_order.write().await;
104 cache.clear();
105 access_order.clear();
106 }
107
108 pub async fn stats(&self) -> CacheStats {
109 let cache = self.cache.read().await;
110 let _access_order = self.access_order.read().await;
111
112 let total_entries = cache.len();
113 let total_accesses: usize = cache.values().map(|e| e.access_count).sum();
114 let total_size: usize = cache.values().map(|e| e.size_estimate).sum();
115 let avg_access_count = if total_entries > 0 {
116 total_accesses as f64 / total_entries as f64
117 } else {
118 0.0
119 };
120
121 CacheStats {
122 total_entries,
123 total_accesses,
124 total_size_bytes: total_size,
125 avg_access_count,
126 hit_rate: 0.0, }
128 }
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct CacheStats {
134 pub total_entries: usize,
135 pub total_accesses: usize,
136 pub total_size_bytes: usize,
137 pub avg_access_count: f64,
138 pub hit_rate: f64,
139}
140
141pub struct ParallelProcessor {
143 max_concurrent_tasks: usize,
144}
145
146impl ParallelProcessor {
147 pub fn new(max_concurrent_tasks: usize) -> Self {
148 Self {
149 max_concurrent_tasks,
150 }
151 }
152
153 pub async fn process_files<F, Fut, T>(
155 &self,
156 files: Vec<PathBuf>,
157 processor: F,
158 ) -> Result<Vec<T>>
159 where
160 F: Fn(PathBuf) -> Fut + Send + Sync + Clone,
161 Fut: std::future::Future<Output = Result<T>> + Send,
162 T: Send,
163 {
164 use futures::stream::{self, StreamExt};
165
166 let results: Vec<Result<T>> = stream::iter(files)
167 .map(|file| {
168 let processor = processor.clone();
169 async move { processor(file).await }
170 })
171 .buffer_unordered(self.max_concurrent_tasks)
172 .collect()
173 .await;
174
175 let mut successful_results = Vec::new();
177 for result in results {
178 successful_results.push(result?);
179 }
180
181 Ok(successful_results)
182 }
183
184 pub async fn process_with_priority<F, Fut, T, P>(
186 &self,
187 files_with_priority: Vec<(PathBuf, P)>,
188 processor: F,
189 ) -> Result<Vec<T>>
190 where
191 F: Fn(PathBuf) -> Fut + Send + Sync + Clone,
192 Fut: std::future::Future<Output = Result<T>> + Send,
193 T: Send,
194 P: Ord + Send,
195 {
196 let mut sorted_files: Vec<_> = files_with_priority;
198 sorted_files.sort_by(|a, b| b.1.cmp(&a.1));
199
200 let files: Vec<PathBuf> = sorted_files.into_iter().map(|(file, _)| file).collect();
201
202 self.process_files(files, processor).await
203 }
204}
205
206pub struct MemoryEfficientStorage {
208 analyses: Arc<RwLock<HashMap<String, CompressedAnalysis>>>,
209 max_memory_mb: usize,
210 current_memory_usage: Arc<RwLock<usize>>,
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
214struct CompressedAnalysis {
215 symbols: Vec<u8>, dependencies: Vec<u8>, metrics: Vec<u8>, original_size: usize,
219 compressed_size: usize,
220}
221
222impl MemoryEfficientStorage {
223 pub fn new(max_memory_mb: usize) -> Self {
224 Self {
225 analyses: Arc::new(RwLock::new(HashMap::new())),
226 max_memory_mb: max_memory_mb * 1024 * 1024, current_memory_usage: Arc::new(RwLock::new(0)),
228 }
229 }
230
231 pub async fn store_analysis(&self, file_path: &Path, analysis: CodeAnalysis) -> Result<()> {
232 let compressed = self.compress_analysis(analysis).await?;
233 let key = file_path.to_string_lossy().to_string();
234
235 let mut analyses = self.analyses.write().await;
236 let mut memory_usage = self.current_memory_usage.write().await;
237
238 if let Some(old_entry) = analyses.remove(&key) {
240 *memory_usage = memory_usage.saturating_sub(old_entry.compressed_size);
241 }
242
243 while *memory_usage + compressed.compressed_size > self.max_memory_mb {
245 if let Some((_, entry)) = analyses.iter().next() {
246 let entry_size = entry.compressed_size;
247 analyses.retain(|_, e| e.compressed_size != entry_size);
248 *memory_usage = memory_usage.saturating_sub(entry_size);
249 break;
250 }
251 }
252
253 analyses.insert(key, compressed.clone());
254 *memory_usage += compressed.compressed_size;
255
256 Ok(())
257 }
258
259 pub async fn get_analysis(&self, file_path: &Path) -> Result<Option<CodeAnalysis>> {
260 let analyses = self.analyses.read().await;
261 let key = file_path.to_string_lossy().to_string();
262
263 if let Some(compressed) = analyses.get(&key) {
264 let analysis = self.decompress_analysis(compressed).await?;
265 Ok(Some(analysis))
266 } else {
267 Ok(None)
268 }
269 }
270
271 async fn compress_analysis(&self, analysis: CodeAnalysis) -> Result<CompressedAnalysis> {
272 use flate2::{Compression, write::GzEncoder};
273 use std::io::Write;
274
275 let serialize_and_compress = |data: &serde_json::Value| -> Result<Vec<u8>> {
276 let json = serde_json::to_vec(data)?;
277 let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
278 encoder.write_all(&json)?;
279 Ok(encoder.finish()?)
280 };
281
282 let symbols = serialize_and_compress(&serde_json::to_value(&analysis.symbols)?)?;
283 let dependencies = serialize_and_compress(&serde_json::to_value(&analysis.dependencies)?)?;
284 let metrics = serialize_and_compress(&serde_json::to_value(&analysis.metrics)?)?;
285
286 let original_size = analysis.symbols.len()
287 + analysis.dependencies.len()
288 + std::mem::size_of_val(&analysis.metrics);
289 let compressed_size = symbols.len() + dependencies.len() + metrics.len();
290
291 Ok(CompressedAnalysis {
292 symbols,
293 dependencies,
294 metrics,
295 original_size,
296 compressed_size,
297 })
298 }
299
300 async fn decompress_analysis(&self, compressed: &CompressedAnalysis) -> Result<CodeAnalysis> {
301 use flate2::read::GzDecoder;
302 use std::io::Read;
303
304 let decompress_and_deserialize = |data: &[u8]| -> Result<serde_json::Value> {
305 let mut decoder = GzDecoder::new(data);
306 let mut decompressed = Vec::new();
307 decoder.read_to_end(&mut decompressed)?;
308 Ok(serde_json::from_slice(&decompressed)?)
309 };
310
311 let symbols: Vec<crate::tools::tree_sitter::languages::SymbolInfo> =
312 decompress_and_deserialize(&compressed.symbols)?
313 .as_array()
314 .unwrap_or(&vec![])
315 .iter()
316 .filter_map(|v| serde_json::from_value(v.clone()).ok())
317 .collect();
318
319 let _dependencies: Vec<String> = decompress_and_deserialize(&compressed.dependencies)?
320 .as_array()
321 .unwrap_or(&vec![])
322 .iter()
323 .filter_map(|v| v.as_str().map(|s| s.to_string()))
324 .collect();
325
326 let metrics: crate::tools::tree_sitter::CodeMetrics =
327 decompress_and_deserialize(&compressed.metrics)?
328 .as_object()
329 .and_then(|obj| serde_json::from_value(serde_json::Value::Object(obj.clone())).ok())
330 .unwrap_or_default();
331
332 Ok(CodeAnalysis {
333 file_path: String::new(), language: crate::tools::tree_sitter::analyzer::LanguageSupport::Rust, symbols,
336 dependencies: Vec::new(), metrics,
338 issues: Vec::new(),
339 complexity: Default::default(),
340 structure: Default::default(),
341 })
342 }
343}
344
345pub struct ResponseOptimizer {
347 response_times: Arc<RwLock<HashMap<String, Vec<Duration>>>>,
348 optimization_strategies: Arc<RwLock<HashMap<String, OptimizationStrategy>>>,
349}
350
351#[derive(Debug, Clone)]
352pub enum OptimizationStrategy {
353 CacheFrequentlyAccessed,
354 PrecomputeResults,
355 ParallelProcessing,
356 ReducePayloadSize,
357 StreamResponse,
358}
359
360impl ResponseOptimizer {
361 pub fn new() -> Self {
362 Self {
363 response_times: Arc::new(RwLock::new(HashMap::new())),
364 optimization_strategies: Arc::new(RwLock::new(HashMap::new())),
365 }
366 }
367
368 pub async fn record_response_time(&self, operation: &str, duration: Duration) {
370 let mut response_times = self.response_times.write().await;
371
372 let times = response_times
373 .entry(operation.to_string())
374 .or_insert_with(Vec::new);
375 times.push(duration);
376
377 if times.len() > 100 {
379 times.remove(0);
380 }
381
382 self.analyze_and_optimize(operation, times).await;
384 }
385
386 pub async fn get_optimization_strategy(&self, operation: &str) -> OptimizationStrategy {
388 let strategies = self.optimization_strategies.read().await;
389
390 strategies
391 .get(operation)
392 .cloned()
393 .unwrap_or(OptimizationStrategy::CacheFrequentlyAccessed)
394 }
395
396 async fn analyze_and_optimize(&self, operation: &str, times: &[Duration]) {
397 if times.len() < 10 {
398 return; }
400
401 let avg_time: Duration = times.iter().sum::<Duration>() / times.len() as u32;
402 let recent_avg: Duration = times.iter().rev().take(5).sum::<Duration>() / 5;
403
404 let mut strategies = self.optimization_strategies.write().await;
405
406 let strategy = if avg_time > Duration::from_millis(1000) {
407 OptimizationStrategy::ParallelProcessing
409 } else if recent_avg > avg_time * 2 {
410 OptimizationStrategy::PrecomputeResults
412 } else if times.len() > 50 {
413 OptimizationStrategy::CacheFrequentlyAccessed
415 } else {
416 OptimizationStrategy::CacheFrequentlyAccessed
418 };
419
420 strategies.insert(operation.to_string(), strategy);
421 }
422
423 pub async fn get_performance_stats(&self) -> HashMap<String, PerformanceStats> {
425 let response_times = self.response_times.read().await;
426 let mut stats = HashMap::new();
427
428 for (operation, times) in response_times.iter() {
429 if times.is_empty() {
430 continue;
431 }
432
433 let avg_time = times.iter().sum::<Duration>() / times.len() as u32;
434 let min_time = times.iter().min().unwrap();
435 let max_time = times.iter().max().unwrap();
436
437 stats.insert(
438 operation.clone(),
439 PerformanceStats {
440 operation: operation.clone(),
441 avg_response_time: avg_time,
442 min_response_time: *min_time,
443 max_response_time: *max_time,
444 total_calls: times.len(),
445 p95_response_time: self.calculate_percentile(times, 95),
446 },
447 );
448 }
449
450 stats
451 }
452
453 fn calculate_percentile(&self, times: &[Duration], percentile: u8) -> Duration {
454 if times.is_empty() {
455 return Duration::from_millis(0);
456 }
457
458 let mut sorted_times = times.to_vec();
459 sorted_times.sort();
460
461 let index = (percentile as f64 / 100.0 * (sorted_times.len() - 1) as f64) as usize;
462 sorted_times[index]
463 }
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize)]
468pub struct PerformanceStats {
469 pub operation: String,
470 pub avg_response_time: Duration,
471 pub min_response_time: Duration,
472 pub max_response_time: Duration,
473 pub total_calls: usize,
474 pub p95_response_time: Duration,
475}
476
477pub struct PerformanceMonitor {
479 start_time: Instant,
480 operation_counts: Arc<RwLock<HashMap<String, usize>>>,
481 error_counts: Arc<RwLock<HashMap<String, usize>>>,
482 memory_usage: Arc<RwLock<Vec<(Instant, usize)>>>,
483}
484
485impl PerformanceMonitor {
486 pub fn new() -> Self {
487 Self {
488 start_time: Instant::now(),
489 operation_counts: Arc::new(RwLock::new(HashMap::new())),
490 error_counts: Arc::new(RwLock::new(HashMap::new())),
491 memory_usage: Arc::new(RwLock::new(Vec::new())),
492 }
493 }
494
495 pub async fn record_operation(&self, operation: &str) {
497 let mut counts = self.operation_counts.write().await;
498 *counts.entry(operation.to_string()).or_insert(0) += 1;
499 }
500
501 pub async fn record_error(&self, operation: &str) {
503 let mut counts = self.error_counts.write().await;
504 *counts.entry(operation.to_string()).or_insert(0) += 1;
505 }
506
507 pub async fn record_memory_usage(&self, usage_bytes: usize) {
509 let mut memory_usage = self.memory_usage.write().await;
510 memory_usage.push((Instant::now(), usage_bytes));
511
512 if memory_usage.len() > 1000 {
514 memory_usage.remove(0);
515 }
516 }
517
518 pub async fn generate_report(&self) -> PerformanceReport {
520 let operation_counts = self.operation_counts.read().await;
521 let error_counts = self.error_counts.read().await;
522 let memory_usage = self.memory_usage.read().await;
523
524 let total_operations: usize = operation_counts.values().sum();
525 let total_errors: usize = error_counts.values().sum();
526
527 let avg_memory_usage = if !memory_usage.is_empty() {
528 memory_usage.iter().map(|(_, usage)| usage).sum::<usize>() / memory_usage.len()
529 } else {
530 0
531 };
532
533 let uptime = self.start_time.elapsed();
534
535 PerformanceReport {
536 uptime,
537 total_operations,
538 total_errors,
539 error_rate: if total_operations > 0 {
540 total_errors as f64 / total_operations as f64
541 } else {
542 0.0
543 },
544 avg_memory_usage,
545 operations_per_second: total_operations as f64 / uptime.as_secs_f64(),
546 operation_breakdown: operation_counts.clone(),
547 error_breakdown: error_counts.clone(),
548 }
549 }
550}
551
552#[derive(Debug, Clone, Serialize, Deserialize)]
554pub struct PerformanceReport {
555 pub uptime: Duration,
556 pub total_operations: usize,
557 pub total_errors: usize,
558 pub error_rate: f64,
559 pub avg_memory_usage: usize,
560 pub operations_per_second: f64,
561 pub operation_breakdown: HashMap<String, usize>,
562 pub error_breakdown: HashMap<String, usize>,
563}