use std::time::Duration;
use crate::config::{
CacheConfig, EventConfig, ExtensionConfig, ForgeConfig, HistoryConfig,
PerformanceConfig, ProcessorConfig, RuntimeConfig, RuntimeType,
};
use super::system_detector::{ResourceTier, SystemResources};
pub struct AdaptiveRuntimeSelector;
impl AdaptiveRuntimeSelector {
pub fn select_runtime(resources: &SystemResources) -> RuntimeType {
match resources.resource_tier() {
ResourceTier::Low => RuntimeType::Sync,
ResourceTier::Medium => RuntimeType::Async,
ResourceTier::High => RuntimeType::Actor,
}
}
pub fn generate_config(resources: &SystemResources) -> ForgeConfig {
let tier = resources.resource_tier();
ForgeConfig {
runtime: RuntimeConfig {
runtime_type: Self::select_runtime(resources),
},
processor: Self::processor_config(resources, tier),
performance: Self::performance_config(resources, tier),
event: Self::event_config(resources, tier),
history: Self::history_config(resources, tier),
extension: ExtensionConfig::default(),
cache: Self::cache_config(resources, tier),
..Default::default()
}
}
fn processor_config(
res: &SystemResources,
tier: ResourceTier,
) -> ProcessorConfig {
ProcessorConfig {
max_queue_size: Self::calc_queue_size(res.available_memory_mb),
max_concurrent_tasks: ((res.cpu_threads as f32 * 0.75) as usize)
.max(2),
task_timeout: match tier {
ResourceTier::High => Duration::from_secs(10),
ResourceTier::Medium => Duration::from_secs(30),
ResourceTier::Low => Duration::from_secs(60),
},
max_retries: match tier {
ResourceTier::High => 3,
ResourceTier::Medium => 3,
ResourceTier::Low => 5,
},
retry_delay: Duration::from_secs(1),
cleanup_timeout: Duration::from_secs(30),
}
}
fn performance_config(
_res: &SystemResources,
tier: ResourceTier,
) -> PerformanceConfig {
PerformanceConfig {
enable_monitoring: tier == ResourceTier::High,
enable_detailed_logging: tier == ResourceTier::High,
middleware_timeout_ms: match tier {
ResourceTier::High => 300, ResourceTier::Medium => 500, ResourceTier::Low => 1000, },
log_threshold_ms: match tier {
ResourceTier::High => 50,
ResourceTier::Medium => 100,
ResourceTier::Low => 200,
},
task_receive_timeout_ms: match tier {
ResourceTier::High => 3000,
ResourceTier::Medium => 5000,
ResourceTier::Low => 10000,
},
metrics_sampling_rate: match tier {
ResourceTier::High => 1.0, ResourceTier::Medium => 0.5, ResourceTier::Low => 0.1, },
}
}
fn event_config(
res: &SystemResources,
tier: ResourceTier,
) -> EventConfig {
EventConfig {
max_queue_size: Self::calc_queue_size(res.available_memory_mb) / 2,
handler_timeout: Duration::from_millis(match tier {
ResourceTier::High => 300,
ResourceTier::Medium => 500,
ResourceTier::Low => 1000,
}),
enable_persistence: tier == ResourceTier::High,
batch_size: match tier {
ResourceTier::High => 200,
ResourceTier::Medium => 100,
ResourceTier::Low => 50,
},
max_concurrent_handlers: (res.cpu_cores / 2).max(1),
}
}
fn history_config(
_res: &SystemResources,
tier: ResourceTier,
) -> HistoryConfig {
HistoryConfig {
max_entries: match tier {
ResourceTier::High => 1000,
ResourceTier::Medium => 500,
ResourceTier::Low => 100,
},
enable_compression: tier == ResourceTier::Low,
persistence_interval: Duration::from_secs(match tier {
ResourceTier::High => 30,
ResourceTier::Medium => 60,
ResourceTier::Low => 120,
}),
}
}
fn cache_config(
_res: &SystemResources,
tier: ResourceTier,
) -> CacheConfig {
CacheConfig {
max_entries: match tier {
ResourceTier::High => 5000,
ResourceTier::Medium => 2000,
ResourceTier::Low => 500,
},
entry_ttl: Duration::from_secs(match tier {
ResourceTier::High => 180, ResourceTier::Medium => 300, ResourceTier::Low => 600, }),
enable_lru: true,
cleanup_interval: Duration::from_secs(60),
}
}
fn calc_queue_size(available_memory_mb: u64) -> usize {
let memory_gb = (available_memory_mb / 1024).max(1);
(memory_gb as usize * 100).clamp(500, 10000)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_select_runtime() {
let low = SystemResources {
cpu_cores: 2,
cpu_threads: 2,
total_memory_mb: 4096,
available_memory_mb: 2048,
};
assert_eq!(
AdaptiveRuntimeSelector::select_runtime(&low),
RuntimeType::Sync
);
let medium = SystemResources {
cpu_cores: 4,
cpu_threads: 8,
total_memory_mb: 8192,
available_memory_mb: 4096,
};
assert_eq!(
AdaptiveRuntimeSelector::select_runtime(&medium),
RuntimeType::Async
);
let high = SystemResources {
cpu_cores: 8,
cpu_threads: 16,
total_memory_mb: 16384,
available_memory_mb: 8192,
};
assert_eq!(
AdaptiveRuntimeSelector::select_runtime(&high),
RuntimeType::Actor
);
}
#[test]
fn test_calc_queue_size() {
assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(2048), 500);
assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(4096), 500);
assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(8192), 800);
assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(16384), 1600);
assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(128 * 1024), 10000);
}
#[test]
fn test_generate_config() {
let resources = SystemResources {
cpu_cores: 4,
cpu_threads: 8,
total_memory_mb: 8192,
available_memory_mb: 4096,
};
let config = AdaptiveRuntimeSelector::generate_config(&resources);
assert_eq!(config.runtime.runtime_type, RuntimeType::Async);
assert_eq!(config.processor.max_concurrent_tasks, 6);
assert_eq!(config.processor.max_queue_size, 500);
assert_eq!(config.performance.middleware_timeout_ms, 500);
}
#[test]
fn test_concurrent_tasks_calculation() {
let low = SystemResources {
cpu_cores: 1,
cpu_threads: 1,
total_memory_mb: 2048,
available_memory_mb: 1024,
};
let config = AdaptiveRuntimeSelector::generate_config(&low);
assert!(
config.processor.max_concurrent_tasks >= 2,
"并发数应该至少为2"
);
let medium = SystemResources {
cpu_cores: 4,
cpu_threads: 8,
total_memory_mb: 8192,
available_memory_mb: 4096,
};
let config = AdaptiveRuntimeSelector::generate_config(&medium);
assert_eq!(config.processor.max_concurrent_tasks, 6, "8 * 0.75 = 6");
}
}