- Fix compilation errors in src/main.rs and resolve import conflicts - Add debian/compat file and ensure debian/rules is executable - Downgrade Cargo.lock to version 3 for compatibility with system cargo - Create working apt-ostree binary with basic CLI functionality - Build apt-ostree_0.1.0-1_amd64.deb package (1.1MB) - Package installs successfully and binary works correctly - Ensure libostree-1-1 (>= 2025.2) dependency for bootc compatibility - Test package installation and basic commands (status, version)
1389 lines
No EOL
52 KiB
Rust
1389 lines
No EOL
52 KiB
Rust
use std::collections::HashMap;
|
|
use std::sync::{Arc, Mutex, RwLock};
|
|
use std::time::{Duration, Instant};
|
|
use tokio::sync::Semaphore;
|
|
use tracing::{info, warn};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// Performance optimization manager
|
|
pub struct PerformanceManager {
|
|
cache: Arc<RwLock<Cache>>,
|
|
metrics: Arc<Mutex<MetricsCollector>>,
|
|
parallel_semaphore: Arc<Semaphore>,
|
|
memory_pool: Arc<Mutex<MemoryPool>>,
|
|
advanced_config: Option<AdvancedPerformanceConfig>,
|
|
adaptive_cache: Option<Arc<Mutex<AdaptiveCacheManager>>>,
|
|
intelligent_memory: Option<Arc<Mutex<IntelligentMemoryManager>>>,
|
|
predictor: Option<Arc<Mutex<PerformancePredictor>>>,
|
|
}
|
|
|
|
/// Cache for frequently accessed data
|
|
#[derive(Debug)]
|
|
struct Cache {
|
|
package_cache: HashMap<String, CachedPackage>,
|
|
deployment_cache: HashMap<String, CachedDeployment>,
|
|
filesystem_cache: HashMap<String, CachedFilesystem>,
|
|
last_cleanup: Instant,
|
|
}
|
|
|
|
/// Cached package information
|
|
#[derive(Debug, Clone)]
|
|
struct CachedPackage {
|
|
data: PackageData,
|
|
created_at: Instant,
|
|
access_count: u64,
|
|
last_accessed: Instant,
|
|
}
|
|
|
|
/// Cached deployment information
|
|
#[derive(Debug, Clone)]
|
|
struct CachedDeployment {
|
|
data: DeploymentData,
|
|
created_at: Instant,
|
|
access_count: u64,
|
|
last_accessed: Instant,
|
|
}
|
|
|
|
/// Cached filesystem information
|
|
#[derive(Debug, Clone)]
|
|
struct CachedFilesystem {
|
|
data: FilesystemData,
|
|
created_at: Instant,
|
|
access_count: u64,
|
|
last_accessed: Instant,
|
|
}
|
|
|
|
/// Package data structure
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct PackageData {
|
|
pub name: String,
|
|
pub version: String,
|
|
pub dependencies: Vec<String>,
|
|
pub conflicts: Vec<String>,
|
|
pub provides: Vec<String>,
|
|
pub description: Option<String>,
|
|
pub size: u64,
|
|
}
|
|
|
|
/// Deployment data structure
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct DeploymentData {
|
|
pub commit_checksum: String,
|
|
pub packages: Vec<PackageData>,
|
|
pub filesystem_info: FilesystemData,
|
|
pub metadata: String,
|
|
pub created_at: u64,
|
|
}
|
|
|
|
/// Filesystem data structure
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct FilesystemData {
|
|
pub total_files: u64,
|
|
pub total_directories: u64,
|
|
pub total_size: u64,
|
|
pub file_types: HashMap<String, u64>,
|
|
}
|
|
|
|
/// Metrics collector for performance monitoring
|
|
#[derive(Debug)]
|
|
struct MetricsCollector {
|
|
operation_times: HashMap<String, Vec<Duration>>,
|
|
cache_hits: u64,
|
|
cache_misses: u64,
|
|
memory_usage: u64,
|
|
parallel_operations: u64,
|
|
errors: Vec<ErrorMetric>,
|
|
}
|
|
|
|
/// Error metric for tracking performance issues
|
|
#[derive(Debug, Clone)]
|
|
struct ErrorMetric {
|
|
operation: String,
|
|
error: String,
|
|
timestamp: Instant,
|
|
duration: Duration,
|
|
}
|
|
|
|
/// Memory pool for efficient memory management
|
|
#[derive(Debug)]
|
|
struct MemoryPool {
|
|
buffers: Vec<Vec<u8>>,
|
|
max_buffer_size: usize,
|
|
total_allocated: usize,
|
|
peak_usage: usize,
|
|
}
|
|
|
|
/// Advanced performance configuration
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AdvancedPerformanceConfig {
|
|
pub adaptive_caching: bool,
|
|
pub intelligent_memory_management: bool,
|
|
pub performance_prediction: bool,
|
|
pub auto_optimization: bool,
|
|
pub cache_eviction_strategy: CacheEvictionStrategy,
|
|
pub memory_pressure_threshold: f64,
|
|
pub performance_monitoring_interval: u64,
|
|
pub optimization_trigger_threshold: f64,
|
|
pub max_parallel_ops: Option<usize>,
|
|
pub max_memory_mb: Option<usize>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum CacheEvictionStrategy {
|
|
LRU,
|
|
LFU,
|
|
Adaptive,
|
|
TimeBased,
|
|
}
|
|
|
|
impl Default for AdvancedPerformanceConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
adaptive_caching: true,
|
|
intelligent_memory_management: true,
|
|
performance_prediction: true,
|
|
auto_optimization: true,
|
|
cache_eviction_strategy: CacheEvictionStrategy::Adaptive,
|
|
memory_pressure_threshold: 0.8,
|
|
performance_monitoring_interval: 60,
|
|
optimization_trigger_threshold: 0.7,
|
|
max_parallel_ops: None,
|
|
max_memory_mb: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Performance prediction model
|
|
#[derive(Debug)]
|
|
struct PerformancePredictor {
|
|
historical_data: Vec<PerformanceDataPoint>,
|
|
prediction_model: Option<PredictionModel>,
|
|
last_prediction: Option<PerformancePrediction>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct PerformanceDataPoint {
|
|
timestamp: chrono::DateTime<chrono::Utc>,
|
|
operation_type: String,
|
|
duration: Duration,
|
|
memory_usage: u64,
|
|
cache_hit_rate: f64,
|
|
parallel_operations: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct PredictionModel {
|
|
model_type: String,
|
|
accuracy: f64,
|
|
last_updated: chrono::DateTime<chrono::Utc>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct PerformancePrediction {
|
|
operation_type: String,
|
|
predicted_duration: Duration,
|
|
confidence: f64,
|
|
recommended_optimizations: Vec<String>,
|
|
}
|
|
|
|
/// Adaptive cache manager
|
|
#[derive(Debug)]
|
|
struct AdaptiveCacheManager {
|
|
cache_stats: HashMap<String, CacheStats>,
|
|
eviction_policy: CacheEvictionStrategy,
|
|
adaptive_thresholds: HashMap<String, f64>,
|
|
performance_history: Vec<CachePerformancePoint>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct CacheStats {
|
|
hits: u64,
|
|
misses: u64,
|
|
evictions: u64,
|
|
size: usize,
|
|
last_access: Instant,
|
|
access_frequency: f64,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct CachePerformancePoint {
|
|
timestamp: chrono::DateTime<chrono::Utc>,
|
|
hit_rate: f64,
|
|
memory_usage: u64,
|
|
eviction_rate: f64,
|
|
}
|
|
|
|
/// Intelligent memory manager
|
|
#[derive(Debug)]
|
|
struct IntelligentMemoryManager {
|
|
memory_pressure_history: Vec<MemoryPressurePoint>,
|
|
allocation_patterns: HashMap<String, AllocationPattern>,
|
|
optimization_suggestions: Vec<MemoryOptimization>,
|
|
auto_cleanup_enabled: bool,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct MemoryPressurePoint {
|
|
timestamp: chrono::DateTime<chrono::Utc>,
|
|
pressure_level: f64,
|
|
available_memory: u64,
|
|
total_memory: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct AllocationPattern {
|
|
pattern_type: String,
|
|
frequency: u64,
|
|
average_size: u64,
|
|
lifetime: Duration,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct MemoryOptimization {
|
|
optimization_type: String,
|
|
description: String,
|
|
expected_improvement: f64,
|
|
implementation_cost: OptimizationCost,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
enum OptimizationCost {
|
|
Low,
|
|
Medium,
|
|
High,
|
|
}
|
|
|
|
impl PerformanceManager {
|
|
/// Create a new performance manager
|
|
pub fn new(max_parallel_ops: usize, max_memory_mb: usize) -> Self {
|
|
let cache = Arc::new(RwLock::new(Cache {
|
|
package_cache: HashMap::new(),
|
|
deployment_cache: HashMap::new(),
|
|
filesystem_cache: HashMap::new(),
|
|
last_cleanup: Instant::now(),
|
|
}));
|
|
|
|
let metrics = Arc::new(Mutex::new(MetricsCollector {
|
|
operation_times: HashMap::new(),
|
|
cache_hits: 0,
|
|
cache_misses: 0,
|
|
memory_usage: 0,
|
|
parallel_operations: 0,
|
|
errors: Vec::new(),
|
|
}));
|
|
|
|
let parallel_semaphore = Arc::new(Semaphore::new(max_parallel_ops));
|
|
let memory_pool = Arc::new(Mutex::new(MemoryPool {
|
|
buffers: Vec::new(),
|
|
max_buffer_size: max_memory_mb * 1024 * 1024,
|
|
total_allocated: 0,
|
|
peak_usage: 0,
|
|
}));
|
|
|
|
PerformanceManager {
|
|
cache,
|
|
metrics,
|
|
parallel_semaphore,
|
|
memory_pool,
|
|
advanced_config: None,
|
|
adaptive_cache: None,
|
|
intelligent_memory: None,
|
|
predictor: None,
|
|
}
|
|
}
|
|
|
|
/// Create a new performance manager with advanced features
|
|
pub fn new_advanced(config: AdvancedPerformanceConfig) -> Self {
|
|
let basic_config = PerformanceConfig {
|
|
max_cache_size: 1000,
|
|
max_memory_mb: 512,
|
|
max_parallel_ops: 10,
|
|
cache_ttl_seconds: 3600,
|
|
enable_metrics: true,
|
|
enable_memory_pool: true,
|
|
};
|
|
|
|
let cache = Arc::new(RwLock::new(Cache {
|
|
package_cache: HashMap::new(),
|
|
deployment_cache: HashMap::new(),
|
|
filesystem_cache: HashMap::new(),
|
|
last_cleanup: Instant::now(),
|
|
}));
|
|
|
|
let metrics = Arc::new(Mutex::new(MetricsCollector {
|
|
operation_times: HashMap::new(),
|
|
cache_hits: 0,
|
|
cache_misses: 0,
|
|
memory_usage: 0,
|
|
parallel_operations: 0,
|
|
errors: Vec::new(),
|
|
}));
|
|
|
|
let parallel_semaphore = Arc::new(Semaphore::new(config.max_parallel_ops.unwrap_or(10)));
|
|
let memory_pool = Arc::new(Mutex::new(MemoryPool {
|
|
buffers: Vec::new(),
|
|
max_buffer_size: config.max_memory_mb.unwrap_or(512) * 1024 * 1024,
|
|
total_allocated: 0,
|
|
peak_usage: 0,
|
|
}));
|
|
|
|
// Initialize advanced components
|
|
let adaptive_cache = if config.adaptive_caching {
|
|
Some(Arc::new(Mutex::new(AdaptiveCacheManager {
|
|
cache_stats: HashMap::new(),
|
|
eviction_policy: config.cache_eviction_strategy.clone(),
|
|
adaptive_thresholds: HashMap::new(),
|
|
performance_history: Vec::new(),
|
|
})))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let intelligent_memory = if config.intelligent_memory_management {
|
|
Some(Arc::new(Mutex::new(IntelligentMemoryManager {
|
|
memory_pressure_history: Vec::new(),
|
|
allocation_patterns: HashMap::new(),
|
|
optimization_suggestions: Vec::new(),
|
|
auto_cleanup_enabled: config.auto_optimization,
|
|
})))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let predictor = if config.performance_prediction {
|
|
Some(Arc::new(Mutex::new(PerformancePredictor {
|
|
historical_data: Vec::new(),
|
|
prediction_model: None,
|
|
last_prediction: None,
|
|
})))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
PerformanceManager {
|
|
cache,
|
|
metrics,
|
|
parallel_semaphore,
|
|
memory_pool,
|
|
advanced_config: Some(config),
|
|
adaptive_cache,
|
|
intelligent_memory,
|
|
predictor,
|
|
}
|
|
}
|
|
|
|
/// Get package data with caching
|
|
pub async fn get_package_data(&self, package_name: &str) -> Result<Option<PackageData>, Box<dyn std::error::Error + Send + Sync>> {
|
|
let start_time = Instant::now();
|
|
|
|
// Check cache first - release lock before await
|
|
let cached_data = {
|
|
let cache = self.cache.read().unwrap();
|
|
cache.package_cache.get(package_name).cloned()
|
|
};
|
|
|
|
if let Some(cached_package) = cached_data {
|
|
// Update access count and last accessed time
|
|
{
|
|
let mut cache = self.cache.write().unwrap();
|
|
if let Some(cached_package) = cache.package_cache.get_mut(package_name) {
|
|
cached_package.access_count += 1;
|
|
cached_package.last_accessed = Instant::now();
|
|
}
|
|
}
|
|
|
|
// Update metrics separately
|
|
{
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.cache_hits += 1;
|
|
metrics.operation_times.entry("cache_hit".to_string()).or_insert_with(Vec::new).push(start_time.elapsed());
|
|
}
|
|
|
|
return Ok(Some(cached_package.data.clone()));
|
|
}
|
|
|
|
// Cache miss - fetch from source
|
|
{
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.cache_misses += 1;
|
|
}
|
|
|
|
let package_data = self.fetch_package_data_internal(package_name).await?;
|
|
|
|
// Cache the result
|
|
if let Some(data) = &package_data {
|
|
// Apply adaptive eviction if cache is full
|
|
if self.cache.read().unwrap().package_cache.len() >= 1000 {
|
|
drop(self.cache.read().unwrap()); // Release lock before await
|
|
self.apply_adaptive_eviction_packages(&mut self.cache.write().unwrap().package_cache).await?;
|
|
let mut cache = self.cache.write().unwrap();
|
|
cache.package_cache.insert(package_name.to_string(), CachedPackage {
|
|
data: data.clone(),
|
|
created_at: Instant::now(),
|
|
access_count: 1,
|
|
last_accessed: Instant::now(),
|
|
});
|
|
} else {
|
|
let mut cache = self.cache.write().unwrap();
|
|
cache.package_cache.insert(package_name.to_string(), CachedPackage {
|
|
data: data.clone(),
|
|
created_at: Instant::now(),
|
|
access_count: 1,
|
|
last_accessed: Instant::now(),
|
|
});
|
|
}
|
|
}
|
|
|
|
Ok(package_data)
|
|
}
|
|
|
|
/// Get package data with adaptive caching
|
|
pub async fn get_package_data_adaptive(&self, package_name: &str) -> Result<Option<PackageData>, Box<dyn std::error::Error + Send + Sync>> {
|
|
let start_time = Instant::now();
|
|
|
|
// Check if adaptive caching is enabled
|
|
if let Some(adaptive_cache) = &self.adaptive_cache {
|
|
// Update adaptive cache statistics
|
|
{
|
|
let mut cache_manager = adaptive_cache.lock().unwrap();
|
|
|
|
// Collect data before multiple borrows
|
|
let threshold = cache_manager.adaptive_thresholds.get(package_name).unwrap_or(&0.5).clone();
|
|
|
|
let stats = cache_manager.cache_stats.entry(package_name.to_string()).or_insert(CacheStats {
|
|
hits: 0,
|
|
misses: 0,
|
|
evictions: 0,
|
|
size: 0,
|
|
access_frequency: 0.0,
|
|
last_access: Instant::now(),
|
|
});
|
|
|
|
// Collect data before multiple borrows
|
|
let access_frequency = stats.access_frequency;
|
|
let evictions = stats.evictions;
|
|
let hits = stats.hits;
|
|
let misses = stats.misses;
|
|
|
|
// Update stats
|
|
stats.hits += 1;
|
|
stats.access_frequency = access_frequency * 0.9 + 0.1; // Exponential moving average
|
|
stats.last_access = Instant::now();
|
|
|
|
// Calculate eviction rate
|
|
let eviction_rate = if hits + misses > 0 {
|
|
evictions as f64 / (hits + misses) as f64
|
|
} else {
|
|
0.0
|
|
};
|
|
|
|
// Add performance history point
|
|
cache_manager.performance_history.push(CachePerformancePoint {
|
|
timestamp: chrono::Utc::now(),
|
|
hit_rate: access_frequency,
|
|
memory_usage: self.memory_pool.lock().unwrap().total_allocated as u64,
|
|
eviction_rate,
|
|
});
|
|
}
|
|
|
|
// Check cache with adaptive threshold
|
|
if let Some(cached) = self.cache.read().unwrap().package_cache.get(package_name) {
|
|
return Ok(Some(cached.data.clone()));
|
|
} else {
|
|
// Cache miss - fetch from source
|
|
let package_data = self.get_package_data(package_name).await?;
|
|
|
|
// Cache the result with adaptive strategy
|
|
if let Some(data) = &package_data {
|
|
let mut cache = self.cache.write().unwrap();
|
|
|
|
// Apply adaptive eviction if needed
|
|
if cache.package_cache.len() >= 1000 {
|
|
self.apply_adaptive_eviction(&mut cache.package_cache).await?;
|
|
}
|
|
|
|
cache.package_cache.insert(package_name.to_string(), CachedPackage {
|
|
data: data.clone(),
|
|
created_at: Instant::now(),
|
|
access_count: 1,
|
|
last_accessed: Instant::now(),
|
|
});
|
|
}
|
|
|
|
return Ok(package_data);
|
|
}
|
|
}
|
|
|
|
// Cache miss - fetch from source
|
|
let package_data = self.get_package_data(package_name).await?;
|
|
|
|
// Cache the result with adaptive strategy
|
|
if let Some(data) = &package_data {
|
|
let mut cache = self.cache.write().unwrap();
|
|
|
|
// Apply adaptive eviction if needed
|
|
if cache.package_cache.len() >= 1000 {
|
|
self.apply_adaptive_eviction(&mut cache.package_cache).await?;
|
|
}
|
|
|
|
cache.package_cache.insert(package_name.to_string(), CachedPackage {
|
|
data: data.clone(),
|
|
created_at: Instant::now(),
|
|
access_count: 1,
|
|
last_accessed: Instant::now(),
|
|
});
|
|
}
|
|
|
|
Ok(package_data)
|
|
}
|
|
|
|
/// Get deployment data with caching
|
|
pub async fn get_deployment_data(&self, commit_checksum: &str) -> Result<Option<DeploymentData>, Box<dyn std::error::Error + Send + Sync>> {
|
|
let start_time = Instant::now();
|
|
|
|
// Check cache first
|
|
{
|
|
let cache = self.cache.read().unwrap();
|
|
if let Some(cached) = cache.deployment_cache.get(commit_checksum) {
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.cache_hits += 1;
|
|
metrics.operation_times.entry("cache_hit".to_string()).or_insert_with(Vec::new).push(start_time.elapsed());
|
|
|
|
return Ok(Some(cached.data.clone()));
|
|
}
|
|
}
|
|
|
|
// Cache miss - fetch from source
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.cache_misses += 1;
|
|
|
|
let deployment_data = self.fetch_deployment_data_internal(commit_checksum).await?;
|
|
|
|
// Cache the result
|
|
if let Some(data) = &deployment_data {
|
|
let mut cache = self.cache.write().unwrap();
|
|
cache.deployment_cache.insert(commit_checksum.to_string(), CachedDeployment {
|
|
data: data.clone(),
|
|
created_at: Instant::now(),
|
|
access_count: 1,
|
|
last_accessed: Instant::now(),
|
|
});
|
|
}
|
|
|
|
metrics.operation_times.entry("deployment_fetch".to_string()).or_insert_with(Vec::new).push(start_time.elapsed());
|
|
|
|
Ok(deployment_data)
|
|
}
|
|
|
|
/// Parallel package processing
|
|
pub async fn process_packages_parallel(&self, packages: &[String]) -> Result<Vec<PackageData>, Box<dyn std::error::Error + Send + Sync>> {
|
|
let start_time = Instant::now();
|
|
let mut results = Vec::new();
|
|
|
|
// Process packages sequentially for now to avoid Send issues
|
|
for package in packages {
|
|
match self.get_package_data(package).await {
|
|
Ok(Some(package_data)) => {
|
|
results.push(package_data);
|
|
}
|
|
Ok(None) => {
|
|
warn!("Package not found: {}", package);
|
|
}
|
|
Err(e) => {
|
|
// Update metrics
|
|
{
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.errors.push(ErrorMetric {
|
|
operation: "parallel_package_processing".to_string(),
|
|
error: e.to_string(),
|
|
timestamp: Instant::now(),
|
|
duration: start_time.elapsed(),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update metrics
|
|
{
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.parallel_operations += 1;
|
|
metrics.operation_times.entry("parallel_processing".to_string()).or_insert_with(Vec::new).push(start_time.elapsed());
|
|
}
|
|
|
|
Ok(results)
|
|
}
|
|
|
|
/// Memory-optimized file processing
|
|
pub async fn process_files_memory_optimized(&self, file_paths: &[String]) -> Result<Vec<FileData>, Box<dyn std::error::Error>> {
|
|
let start_time = Instant::now();
|
|
let mut results = Vec::new();
|
|
|
|
// Get memory buffer from pool
|
|
let buffer = self.get_memory_buffer().await?;
|
|
|
|
for file_path in file_paths {
|
|
let file_data = self.process_file_with_buffer(file_path, &buffer).await?;
|
|
results.push(file_data);
|
|
}
|
|
|
|
// Return buffer to pool
|
|
self.return_memory_buffer(buffer).await?;
|
|
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.operation_times.entry("memory_optimized_processing".to_string()).or_insert_with(Vec::new).push(start_time.elapsed());
|
|
|
|
Ok(results)
|
|
}
|
|
|
|
/// Cache cleanup to prevent memory leaks
|
|
pub async fn cleanup_cache(&self) -> Result<(), Box<dyn std::error::Error>> {
|
|
let start_time = Instant::now();
|
|
|
|
let mut cache = self.cache.write().unwrap();
|
|
let now = Instant::now();
|
|
|
|
// Remove expired entries (older than 1 hour)
|
|
let max_age = Duration::from_secs(3600);
|
|
|
|
cache.package_cache.retain(|_, cached| {
|
|
now.duration_since(cached.created_at) < max_age
|
|
});
|
|
|
|
cache.deployment_cache.retain(|_, cached| {
|
|
now.duration_since(cached.created_at) < max_age
|
|
});
|
|
|
|
cache.filesystem_cache.retain(|_, cached| {
|
|
now.duration_since(cached.created_at) < max_age
|
|
});
|
|
|
|
cache.last_cleanup = now;
|
|
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.operation_times.entry("cache_cleanup".to_string()).or_insert_with(Vec::new).push(start_time.elapsed());
|
|
|
|
info!("Cache cleanup completed");
|
|
Ok(())
|
|
}
|
|
|
|
/// Get performance metrics
|
|
pub fn get_metrics(&self) -> PerformanceMetrics {
|
|
let cache = self.cache.read().unwrap();
|
|
let metrics = self.metrics.lock().unwrap();
|
|
let memory_pool = self.memory_pool.lock().unwrap();
|
|
|
|
let avg_operation_times: HashMap<String, Duration> = metrics.operation_times
|
|
.iter()
|
|
.map(|(operation, times)| {
|
|
let avg = times.iter().sum::<Duration>() / times.len() as u32;
|
|
(operation.clone(), avg)
|
|
})
|
|
.collect();
|
|
|
|
PerformanceMetrics {
|
|
cache_hits: metrics.cache_hits,
|
|
cache_misses: metrics.cache_misses,
|
|
cache_hit_rate: if metrics.cache_hits + metrics.cache_misses > 0 {
|
|
metrics.cache_hits as f64 / (metrics.cache_hits + metrics.cache_misses) as f64
|
|
} else {
|
|
0.0
|
|
},
|
|
memory_usage_mb: memory_pool.total_allocated as f64 / 1024.0 / 1024.0,
|
|
peak_memory_usage_mb: memory_pool.peak_usage as f64 / 1024.0 / 1024.0,
|
|
parallel_operations: metrics.parallel_operations,
|
|
error_count: metrics.errors.len(),
|
|
avg_operation_times,
|
|
cache_size: cache.package_cache.len() + cache.deployment_cache.len() + cache.filesystem_cache.len(),
|
|
}
|
|
}
|
|
|
|
/// Optimize memory usage
|
|
pub async fn optimize_memory(&self) -> Result<(), Box<dyn std::error::Error>> {
|
|
let start_time = Instant::now();
|
|
|
|
// Clean up cache
|
|
self.cleanup_cache().await?;
|
|
|
|
// Compact memory pool
|
|
let mut memory_pool = self.memory_pool.lock().unwrap();
|
|
memory_pool.buffers.retain(|buffer| buffer.len() > 0);
|
|
memory_pool.buffers.shrink_to_fit();
|
|
|
|
let mut metrics = self.metrics.lock().unwrap();
|
|
metrics.operation_times.entry("memory_optimization".to_string()).or_insert_with(Vec::new).push(start_time.elapsed());
|
|
|
|
info!("Memory optimization completed");
|
|
Ok(())
|
|
}
|
|
|
|
/// Intelligent memory optimization
|
|
pub async fn optimize_memory_intelligent(&self) -> Result<Vec<MemoryOptimization>, Box<dyn std::error::Error + Send + Sync>> {
|
|
if let Some(intelligent_memory) = &self.intelligent_memory {
|
|
let mut memory_manager = intelligent_memory.lock().unwrap();
|
|
|
|
// Analyze memory pressure
|
|
let current_pressure = self.calculate_memory_pressure().await.map_err(|e| format!("Memory pressure calculation failed: {}", e))?;
|
|
memory_manager.memory_pressure_history.push(MemoryPressurePoint {
|
|
timestamp: chrono::Utc::now(),
|
|
pressure_level: current_pressure,
|
|
available_memory: 0, // Would get from system
|
|
total_memory: 0, // Would get from system
|
|
});
|
|
|
|
// Generate optimization suggestions
|
|
let mut optimizations = Vec::new();
|
|
|
|
if current_pressure > 0.8 {
|
|
optimizations.push(MemoryOptimization {
|
|
optimization_type: "Aggressive cleanup".to_string(),
|
|
description: "High memory pressure detected, performing aggressive cleanup".to_string(),
|
|
expected_improvement: 0.3,
|
|
implementation_cost: OptimizationCost::Low,
|
|
});
|
|
}
|
|
|
|
if current_pressure > 0.6 {
|
|
optimizations.push(MemoryOptimization {
|
|
optimization_type: "Cache optimization".to_string(),
|
|
description: "Optimizing cache usage to reduce memory footprint".to_string(),
|
|
expected_improvement: 0.2,
|
|
implementation_cost: OptimizationCost::Medium,
|
|
});
|
|
}
|
|
|
|
// Apply optimizations if auto-optimization is enabled
|
|
if memory_manager.auto_cleanup_enabled {
|
|
for optimization in &optimizations {
|
|
self.apply_memory_optimization(optimization).await.map_err(|e| format!("Memory optimization failed: {}", e))?;
|
|
}
|
|
}
|
|
|
|
memory_manager.optimization_suggestions = optimizations.clone();
|
|
|
|
Ok(optimizations)
|
|
} else {
|
|
Err("Intelligent memory management not enabled".into())
|
|
}
|
|
}
|
|
|
|
/// Predict performance for an operation
|
|
pub async fn predict_performance(&self, operation_type: &str, input_size: usize) -> Result<PerformancePrediction, Box<dyn std::error::Error>> {
|
|
if let Some(predictor) = &self.predictor {
|
|
let mut predictor = predictor.lock().unwrap();
|
|
|
|
// Add current data point
|
|
let current_metrics = self.metrics.lock().unwrap();
|
|
let avg_duration = current_metrics.operation_times
|
|
.get(operation_type)
|
|
.and_then(|times| {
|
|
if times.is_empty() {
|
|
None
|
|
} else {
|
|
Some(times.iter().sum::<Duration>() / times.len() as u32)
|
|
}
|
|
})
|
|
.unwrap_or(Duration::from_millis(100));
|
|
|
|
predictor.historical_data.push(PerformanceDataPoint {
|
|
timestamp: chrono::Utc::now(),
|
|
operation_type: operation_type.to_string(),
|
|
duration: avg_duration,
|
|
memory_usage: current_metrics.memory_usage,
|
|
cache_hit_rate: if current_metrics.cache_hits + current_metrics.cache_misses > 0 {
|
|
current_metrics.cache_hits as f64 / (current_metrics.cache_hits + current_metrics.cache_misses) as f64
|
|
} else {
|
|
0.0
|
|
},
|
|
parallel_operations: current_metrics.parallel_operations,
|
|
});
|
|
|
|
// Simple prediction model (linear regression)
|
|
let prediction = self.calculate_performance_prediction(&predictor.historical_data, operation_type, input_size);
|
|
|
|
predictor.last_prediction = Some(prediction.clone());
|
|
|
|
Ok(prediction)
|
|
} else {
|
|
Err("Performance prediction not enabled".into())
|
|
}
|
|
}
|
|
|
|
/// Calculate performance prediction using simple linear regression
|
|
fn calculate_performance_prediction(&self, historical_data: &[PerformanceDataPoint], operation_type: &str, input_size: usize) -> PerformancePrediction {
|
|
let relevant_data: Vec<_> = historical_data
|
|
.iter()
|
|
.filter(|d| d.operation_type == operation_type)
|
|
.collect();
|
|
|
|
if relevant_data.len() < 2 {
|
|
return PerformancePrediction {
|
|
operation_type: operation_type.to_string(),
|
|
predicted_duration: Duration::from_millis(100),
|
|
confidence: 0.1,
|
|
recommended_optimizations: vec!["Insufficient data for accurate prediction".to_string()],
|
|
};
|
|
}
|
|
|
|
// Simple linear regression: duration = a * input_size + b
|
|
let n = relevant_data.len() as f64;
|
|
let sum_x: f64 = relevant_data.iter().map(|d| d.duration.as_millis() as f64).sum();
|
|
let sum_y: f64 = relevant_data.iter().map(|d| d.memory_usage as f64).sum();
|
|
let sum_xy: f64 = relevant_data.iter()
|
|
.map(|d| d.duration.as_millis() as f64 * d.memory_usage as f64)
|
|
.sum();
|
|
let sum_x2: f64 = relevant_data.iter()
|
|
.map(|d| (d.duration.as_millis() as f64).powi(2))
|
|
.sum();
|
|
|
|
let slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x);
|
|
let intercept = (sum_y - slope * sum_x) / n;
|
|
|
|
let predicted_duration_ms = slope * input_size as f64 + intercept;
|
|
let predicted_duration = Duration::from_millis(predicted_duration_ms.max(1.0) as u64);
|
|
|
|
// Calculate confidence based on data consistency
|
|
let avg_duration = sum_x / n;
|
|
let variance = relevant_data.iter()
|
|
.map(|d| (d.duration.as_millis() as f64 - avg_duration).powi(2))
|
|
.sum::<f64>() / n;
|
|
let confidence = (1.0 / (1.0 + variance / 1000.0)).min(1.0);
|
|
|
|
// Generate optimization recommendations
|
|
let mut recommendations = Vec::new();
|
|
if predicted_duration > Duration::from_secs(5) {
|
|
recommendations.push("Consider parallel processing".to_string());
|
|
}
|
|
if input_size > 1000 {
|
|
recommendations.push("Consider caching intermediate results".to_string());
|
|
}
|
|
if confidence < 0.5 {
|
|
recommendations.push("Collect more performance data".to_string());
|
|
}
|
|
|
|
PerformancePrediction {
|
|
operation_type: operation_type.to_string(),
|
|
predicted_duration,
|
|
confidence,
|
|
recommended_optimizations: recommendations,
|
|
}
|
|
}
|
|
|
|
/// Apply adaptive cache eviction
|
|
async fn apply_adaptive_eviction(&self, cache: &mut HashMap<String, CachedPackage>) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
if let Some(adaptive_cache) = &self.adaptive_cache {
|
|
let cache_manager = adaptive_cache.lock().unwrap();
|
|
|
|
// Collect data before multiple borrows
|
|
let eviction_policy = cache_manager.eviction_policy.clone();
|
|
|
|
drop(cache_manager); // Release lock
|
|
|
|
match eviction_policy {
|
|
CacheEvictionStrategy::LRU => {
|
|
// Remove least recently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::LFU => {
|
|
// Remove least frequently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.access_count)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::Adaptive => {
|
|
// Use adaptive strategy based on access patterns
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| {
|
|
let score = v.access_count as f64 / v.last_accessed.elapsed().as_secs() as f64;
|
|
(k.clone(), score)
|
|
}).collect();
|
|
items.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::TimeBased => {
|
|
// Remove items older than threshold
|
|
let threshold = Instant::now() - Duration::from_secs(3600); // 1 hour
|
|
cache.retain(|_, item| item.created_at > threshold);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Apply adaptive cache eviction for packages
|
|
async fn apply_adaptive_eviction_packages(&self, cache: &mut HashMap<String, CachedPackage>) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
if let Some(adaptive_cache) = &self.adaptive_cache {
|
|
let cache_manager = adaptive_cache.lock().unwrap();
|
|
|
|
// Collect data before multiple borrows
|
|
let eviction_policy = cache_manager.eviction_policy.clone();
|
|
let adaptive_thresholds = cache_manager.adaptive_thresholds.clone();
|
|
|
|
drop(cache_manager); // Release lock
|
|
|
|
match eviction_policy {
|
|
CacheEvictionStrategy::LRU => {
|
|
// Remove least recently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::LFU => {
|
|
// Remove least frequently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.access_count)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::Adaptive => {
|
|
// Use adaptive strategy based on access patterns
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| {
|
|
let score = v.access_count as f64 / v.last_accessed.elapsed().as_secs() as f64;
|
|
(k.clone(), score)
|
|
}).collect();
|
|
items.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::TimeBased => {
|
|
// Remove items older than threshold
|
|
let threshold = Instant::now() - Duration::from_secs(3600); // 1 hour
|
|
cache.retain(|_, item| item.created_at > threshold);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Apply adaptive cache eviction for deployments
|
|
async fn apply_adaptive_eviction_deployments(&self, cache: &mut HashMap<String, CachedDeployment>) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
if let Some(adaptive_cache) = &self.adaptive_cache {
|
|
let cache_manager = adaptive_cache.lock().unwrap();
|
|
|
|
// Collect data before multiple borrows
|
|
let eviction_policy = cache_manager.eviction_policy.clone();
|
|
|
|
drop(cache_manager); // Release lock
|
|
|
|
match eviction_policy {
|
|
CacheEvictionStrategy::LRU => {
|
|
// Remove least recently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::LFU => {
|
|
// Remove least frequently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.access_count)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::Adaptive => {
|
|
// Use adaptive strategy based on access patterns
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| {
|
|
let score = v.access_count as f64 / v.last_accessed.elapsed().as_secs() as f64;
|
|
(k.clone(), score)
|
|
}).collect();
|
|
items.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::TimeBased => {
|
|
// Remove items older than threshold
|
|
let threshold = Instant::now() - Duration::from_secs(3600); // 1 hour
|
|
cache.retain(|_, item| item.created_at > threshold);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Apply adaptive cache eviction for filesystem
|
|
async fn apply_adaptive_eviction_filesystem(&self, cache: &mut HashMap<String, CachedFilesystem>) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
if let Some(adaptive_cache) = &self.adaptive_cache {
|
|
let cache_manager = adaptive_cache.lock().unwrap();
|
|
|
|
// Collect data before multiple borrows
|
|
let eviction_policy = cache_manager.eviction_policy.clone();
|
|
|
|
drop(cache_manager); // Release lock
|
|
|
|
match eviction_policy {
|
|
CacheEvictionStrategy::LRU => {
|
|
// Remove least recently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::LFU => {
|
|
// Remove least frequently used items
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| (k.clone(), v.access_count)).collect();
|
|
items.sort_by(|a, b| a.1.cmp(&b.1));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::Adaptive => {
|
|
// Use adaptive strategy based on access patterns
|
|
let mut items: Vec<_> = cache.iter().map(|(k, v)| {
|
|
let score = v.access_count as f64 / v.last_accessed.elapsed().as_secs() as f64;
|
|
(k.clone(), score)
|
|
}).collect();
|
|
items.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
|
|
|
|
// Remove 10% of items
|
|
let to_remove = (items.len() / 10).max(1);
|
|
for (key, _) in items.iter().take(to_remove) {
|
|
cache.remove(key);
|
|
}
|
|
}
|
|
CacheEvictionStrategy::TimeBased => {
|
|
// Remove items older than threshold
|
|
let threshold = Instant::now() - Duration::from_secs(3600); // 1 hour
|
|
cache.retain(|_, item| item.created_at > threshold);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Calculate current memory pressure
|
|
async fn calculate_memory_pressure(&self) -> Result<f64, Box<dyn std::error::Error + Send + Sync>> {
|
|
let memory_pool = self.memory_pool.lock().unwrap();
|
|
let current_usage = memory_pool.total_allocated as f64;
|
|
let max_usage = memory_pool.max_buffer_size as f64;
|
|
|
|
Ok(current_usage / max_usage)
|
|
}
|
|
|
|
/// Apply memory optimization
|
|
async fn apply_memory_optimization(&self, optimization: &MemoryOptimization) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
match optimization.optimization_type.as_str() {
|
|
"Aggressive cleanup" => {
|
|
// Perform aggressive cache cleanup
|
|
let mut cache = self.cache.write().unwrap();
|
|
cache.package_cache.clear();
|
|
cache.deployment_cache.clear();
|
|
cache.filesystem_cache.clear();
|
|
|
|
// Clear memory pool
|
|
let mut memory_pool = self.memory_pool.lock().unwrap();
|
|
memory_pool.buffers.clear();
|
|
memory_pool.total_allocated = 0;
|
|
}
|
|
"Cache optimization" => {
|
|
// Optimize cache by removing least useful items
|
|
// Apply eviction to each cache type separately
|
|
{
|
|
let mut cache = self.cache.write().unwrap();
|
|
self.apply_adaptive_eviction_packages(&mut cache.package_cache).await?;
|
|
self.apply_adaptive_eviction_deployments(&mut cache.deployment_cache).await?;
|
|
self.apply_adaptive_eviction_filesystem(&mut cache.filesystem_cache).await?;
|
|
}
|
|
}
|
|
_ => {
|
|
warn!("Unknown optimization type: {}", optimization.optimization_type);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Get advanced performance metrics
|
|
pub fn get_advanced_metrics(&self) -> AdvancedPerformanceMetrics {
|
|
let basic_metrics = self.get_metrics();
|
|
|
|
AdvancedPerformanceMetrics {
|
|
basic_metrics,
|
|
cache_efficiency: self.calculate_cache_efficiency(),
|
|
memory_efficiency: self.calculate_memory_efficiency(),
|
|
parallel_efficiency: self.calculate_parallel_efficiency(),
|
|
prediction_accuracy: self.calculate_prediction_accuracy(),
|
|
optimization_effectiveness: self.calculate_optimization_effectiveness(),
|
|
}
|
|
}
|
|
|
|
/// Calculate cache efficiency
|
|
fn calculate_cache_efficiency(&self) -> f64 {
|
|
let metrics = self.metrics.lock().unwrap();
|
|
if metrics.cache_hits + metrics.cache_misses > 0 {
|
|
metrics.cache_hits as f64 / (metrics.cache_hits + metrics.cache_misses) as f64
|
|
} else {
|
|
0.0
|
|
}
|
|
}
|
|
|
|
/// Calculate memory efficiency
|
|
fn calculate_memory_efficiency(&self) -> f64 {
|
|
let memory_pool = self.memory_pool.lock().unwrap();
|
|
if memory_pool.max_buffer_size > 0 {
|
|
1.0 - (memory_pool.total_allocated as f64 / memory_pool.max_buffer_size as f64)
|
|
} else {
|
|
0.0
|
|
}
|
|
}
|
|
|
|
/// Calculate parallel efficiency
|
|
fn calculate_parallel_efficiency(&self) -> f64 {
|
|
let metrics = self.metrics.lock().unwrap();
|
|
if metrics.parallel_operations > 0 {
|
|
// Simple efficiency calculation based on operation times
|
|
let avg_time = metrics.operation_times.values()
|
|
.flat_map(|times| times.iter())
|
|
.sum::<Duration>();
|
|
let total_operations = metrics.operation_times.values()
|
|
.map(|times| times.len())
|
|
.sum::<usize>();
|
|
|
|
if total_operations > 0 {
|
|
let avg_operation_time = avg_time / total_operations as u32;
|
|
// Efficiency decreases with longer operations
|
|
1.0 / (1.0 + avg_operation_time.as_millis() as f64 / 1000.0)
|
|
} else {
|
|
0.0
|
|
}
|
|
} else {
|
|
0.0
|
|
}
|
|
}
|
|
|
|
/// Calculate prediction accuracy
|
|
fn calculate_prediction_accuracy(&self) -> f64 {
|
|
if let Some(predictor) = &self.predictor {
|
|
let predictor = predictor.lock().unwrap();
|
|
if let Some(last_prediction) = &predictor.last_prediction {
|
|
// Simple accuracy calculation based on confidence
|
|
last_prediction.confidence
|
|
} else {
|
|
0.0
|
|
}
|
|
} else {
|
|
0.0
|
|
}
|
|
}
|
|
|
|
/// Calculate optimization effectiveness
|
|
fn calculate_optimization_effectiveness(&self) -> f64 {
|
|
if let Some(intelligent_memory) = &self.intelligent_memory {
|
|
let memory_manager = intelligent_memory.lock().unwrap();
|
|
let recent_optimizations = memory_manager.optimization_suggestions.len();
|
|
|
|
// Effectiveness based on number of optimizations applied
|
|
if recent_optimizations > 0 {
|
|
(recent_optimizations as f64).min(1.0)
|
|
} else {
|
|
0.0
|
|
}
|
|
} else {
|
|
0.0
|
|
}
|
|
}
|
|
|
|
// Helper methods
|
|
pub async fn get_memory_buffer(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
|
let mut memory_pool = self.memory_pool.lock().unwrap();
|
|
|
|
if let Some(buffer) = memory_pool.buffers.pop() {
|
|
memory_pool.total_allocated -= buffer.len();
|
|
Ok(buffer)
|
|
} else {
|
|
// Create new buffer if pool is empty
|
|
let buffer = vec![0u8; 1024 * 1024]; // 1MB buffer
|
|
memory_pool.total_allocated += buffer.len();
|
|
memory_pool.peak_usage = memory_pool.peak_usage.max(memory_pool.total_allocated);
|
|
Ok(buffer)
|
|
}
|
|
}
|
|
|
|
/// Return memory buffer to pool
|
|
async fn return_memory_buffer(&self, buffer: Vec<u8>) -> Result<(), Box<dyn std::error::Error>> {
|
|
let buffer_len = buffer.len();
|
|
let mut memory_pool = self.memory_pool.lock().unwrap();
|
|
|
|
if memory_pool.total_allocated + buffer_len <= memory_pool.max_buffer_size {
|
|
memory_pool.buffers.push(buffer);
|
|
memory_pool.total_allocated += buffer_len;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn process_file_with_buffer(&self, file_path: &str, buffer: &[u8]) -> Result<FileData, Box<dyn std::error::Error>> {
|
|
// Simulate file processing with buffer
|
|
tokio::time::sleep(Duration::from_millis(5)).await;
|
|
|
|
Ok(FileData {
|
|
path: file_path.to_string(),
|
|
size: buffer.len() as u64,
|
|
processed: true,
|
|
})
|
|
}
|
|
|
|
async fn fetch_package_data_internal(&self, package_name: &str) -> Result<Option<PackageData>, Box<dyn std::error::Error + Send + Sync>> {
|
|
// Simulate fetching from APT database
|
|
tokio::time::sleep(Duration::from_millis(10)).await;
|
|
|
|
Ok(Some(PackageData {
|
|
name: package_name.to_string(),
|
|
version: "1.0.0".to_string(),
|
|
dependencies: vec!["libc6".to_string()],
|
|
conflicts: Vec::new(),
|
|
provides: Vec::new(),
|
|
description: Some("Sample package".to_string()),
|
|
size: 1024,
|
|
}))
|
|
}
|
|
|
|
async fn fetch_deployment_data_internal(&self, commit_checksum: &str) -> Result<Option<DeploymentData>, Box<dyn std::error::Error + Send + Sync>> {
|
|
// Simulate fetching from OSTree repository
|
|
tokio::time::sleep(Duration::from_millis(20)).await;
|
|
|
|
Ok(Some(DeploymentData {
|
|
commit_checksum: commit_checksum.to_string(),
|
|
packages: vec![PackageData {
|
|
name: "sample-package".to_string(),
|
|
version: "1.0.0".to_string(),
|
|
dependencies: vec!["libc6".to_string()],
|
|
conflicts: Vec::new(),
|
|
provides: Vec::new(),
|
|
description: Some("Sample package".to_string()),
|
|
size: 2048,
|
|
}],
|
|
filesystem_info: FilesystemData {
|
|
total_files: 1000,
|
|
total_directories: 100,
|
|
total_size: 1024 * 1024,
|
|
file_types: HashMap::new(),
|
|
},
|
|
metadata: "Sample deployment metadata".to_string(),
|
|
created_at: chrono::Utc::now().timestamp() as u64,
|
|
}))
|
|
}
|
|
}
|
|
|
|
impl Clone for PerformanceManager {
|
|
fn clone(&self) -> Self {
|
|
PerformanceManager {
|
|
cache: self.cache.clone(),
|
|
metrics: self.metrics.clone(),
|
|
parallel_semaphore: self.parallel_semaphore.clone(),
|
|
memory_pool: self.memory_pool.clone(),
|
|
advanced_config: self.advanced_config.clone(),
|
|
adaptive_cache: self.adaptive_cache.clone(),
|
|
intelligent_memory: self.intelligent_memory.clone(),
|
|
predictor: self.predictor.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Performance metrics structure
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct PerformanceMetrics {
|
|
pub cache_hits: u64,
|
|
pub cache_misses: u64,
|
|
pub cache_hit_rate: f64,
|
|
pub memory_usage_mb: f64,
|
|
pub peak_memory_usage_mb: f64,
|
|
pub parallel_operations: u64,
|
|
pub error_count: usize,
|
|
pub avg_operation_times: HashMap<String, Duration>,
|
|
pub cache_size: usize,
|
|
}
|
|
|
|
/// Advanced performance metrics
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AdvancedPerformanceMetrics {
|
|
pub basic_metrics: PerformanceMetrics,
|
|
pub cache_efficiency: f64,
|
|
pub memory_efficiency: f64,
|
|
pub parallel_efficiency: f64,
|
|
pub prediction_accuracy: f64,
|
|
pub optimization_effectiveness: f64,
|
|
}
|
|
|
|
/// File data structure
|
|
#[derive(Debug, Clone)]
|
|
pub struct FileData {
|
|
pub path: String,
|
|
pub size: u64,
|
|
pub processed: bool,
|
|
}
|
|
|
|
/// Performance optimization configuration
|
|
#[derive(Debug, Clone)]
|
|
pub struct PerformanceConfig {
|
|
pub max_cache_size: usize,
|
|
pub max_memory_mb: usize,
|
|
pub max_parallel_ops: usize,
|
|
pub cache_ttl_seconds: u64,
|
|
pub enable_metrics: bool,
|
|
pub enable_memory_pool: bool,
|
|
}
|
|
|
|
impl Default for PerformanceConfig {
|
|
fn default() -> Self {
|
|
PerformanceConfig {
|
|
max_cache_size: 1000,
|
|
max_memory_mb: 512,
|
|
max_parallel_ops: 10,
|
|
cache_ttl_seconds: 3600,
|
|
enable_metrics: true,
|
|
enable_memory_pool: true,
|
|
}
|
|
}
|
|
}
|