1use std::time::Duration;
32
33use crate::config::{
34 CacheConfig, EventConfig, ExtensionConfig, ForgeConfig, HistoryConfig,
35 PerformanceConfig, ProcessorConfig, RuntimeConfig, RuntimeType,
36};
37
38use super::system_detector::{ResourceTier, SystemResources};
39
40pub struct AdaptiveRuntimeSelector;
42
43impl AdaptiveRuntimeSelector {
44 pub fn select_runtime(resources: &SystemResources) -> RuntimeType {
64 match resources.resource_tier() {
65 ResourceTier::Low => RuntimeType::Sync,
66 ResourceTier::Medium => RuntimeType::Async,
67 ResourceTier::High => RuntimeType::Actor,
68 }
69 }
70
71 pub fn generate_config(resources: &SystemResources) -> ForgeConfig {
92 let tier = resources.resource_tier();
93
94 ForgeConfig {
95 runtime: RuntimeConfig {
96 runtime_type: Self::select_runtime(resources),
97 },
98 processor: Self::processor_config(resources, tier),
99 performance: Self::performance_config(resources, tier),
100 event: Self::event_config(resources, tier),
101 history: Self::history_config(resources, tier),
102 extension: ExtensionConfig::default(),
103 cache: Self::cache_config(resources, tier),
104 ..Default::default()
105 }
106 }
107
108 fn processor_config(
115 res: &SystemResources,
116 tier: ResourceTier,
117 ) -> ProcessorConfig {
118 ProcessorConfig {
119 max_queue_size: Self::calc_queue_size(res.available_memory_mb),
121
122 max_concurrent_tasks: ((res.cpu_threads as f32 * 0.75) as usize)
124 .max(2),
125
126 task_timeout: match tier {
128 ResourceTier::High => Duration::from_secs(10),
129 ResourceTier::Medium => Duration::from_secs(30),
130 ResourceTier::Low => Duration::from_secs(60),
131 },
132
133 max_retries: match tier {
135 ResourceTier::High => 3,
136 ResourceTier::Medium => 3,
137 ResourceTier::Low => 5,
138 },
139
140 retry_delay: Duration::from_secs(1),
141 cleanup_timeout: Duration::from_secs(30),
142 }
143 }
144
145 fn performance_config(
152 _res: &SystemResources,
153 tier: ResourceTier,
154 ) -> PerformanceConfig {
155 PerformanceConfig {
156 enable_monitoring: tier == ResourceTier::High,
158 enable_detailed_logging: tier == ResourceTier::High,
159
160 middleware_timeout_ms: match tier {
162 ResourceTier::High => 300, ResourceTier::Medium => 500, ResourceTier::Low => 1000, },
166
167 log_threshold_ms: match tier {
169 ResourceTier::High => 50,
170 ResourceTier::Medium => 100,
171 ResourceTier::Low => 200,
172 },
173
174 task_receive_timeout_ms: match tier {
176 ResourceTier::High => 3000,
177 ResourceTier::Medium => 5000,
178 ResourceTier::Low => 10000,
179 },
180
181 metrics_sampling_rate: match tier {
183 ResourceTier::High => 1.0, ResourceTier::Medium => 0.5, ResourceTier::Low => 0.1, },
187 }
188 }
189
190 fn event_config(
197 res: &SystemResources,
198 tier: ResourceTier,
199 ) -> EventConfig {
200 EventConfig {
201 max_queue_size: Self::calc_queue_size(res.available_memory_mb) / 2,
203
204 handler_timeout: Duration::from_millis(match tier {
206 ResourceTier::High => 300,
207 ResourceTier::Medium => 500,
208 ResourceTier::Low => 1000,
209 }),
210
211 enable_persistence: tier == ResourceTier::High,
213
214 batch_size: match tier {
216 ResourceTier::High => 200,
217 ResourceTier::Medium => 100,
218 ResourceTier::Low => 50,
219 },
220
221 max_concurrent_handlers: (res.cpu_cores / 2).max(1),
223 }
224 }
225
226 fn history_config(
232 _res: &SystemResources,
233 tier: ResourceTier,
234 ) -> HistoryConfig {
235 HistoryConfig {
236 max_entries: match tier {
238 ResourceTier::High => 1000,
239 ResourceTier::Medium => 500,
240 ResourceTier::Low => 100,
241 },
242
243 enable_compression: tier == ResourceTier::Low,
245
246 persistence_interval: Duration::from_secs(match tier {
248 ResourceTier::High => 30,
249 ResourceTier::Medium => 60,
250 ResourceTier::Low => 120,
251 }),
252 }
253 }
254
255 fn cache_config(
257 _res: &SystemResources,
258 tier: ResourceTier,
259 ) -> CacheConfig {
260 CacheConfig {
261 max_entries: match tier {
263 ResourceTier::High => 5000,
264 ResourceTier::Medium => 2000,
265 ResourceTier::Low => 500,
266 },
267
268 entry_ttl: Duration::from_secs(match tier {
270 ResourceTier::High => 180, ResourceTier::Medium => 300, ResourceTier::Low => 600, }),
274
275 enable_lru: true,
276
277 cleanup_interval: Duration::from_secs(60),
279 }
280 }
281
282 fn calc_queue_size(available_memory_mb: u64) -> usize {
293 let memory_gb = (available_memory_mb / 1024).max(1);
294 (memory_gb as usize * 100).clamp(500, 10000)
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301
302 #[test]
303 fn test_select_runtime() {
304 let low = SystemResources {
306 cpu_cores: 2,
307 cpu_threads: 2,
308 total_memory_mb: 4096,
309 available_memory_mb: 2048,
310 };
311 assert_eq!(
312 AdaptiveRuntimeSelector::select_runtime(&low),
313 RuntimeType::Sync
314 );
315
316 let medium = SystemResources {
318 cpu_cores: 4,
319 cpu_threads: 8,
320 total_memory_mb: 8192,
321 available_memory_mb: 4096,
322 };
323 assert_eq!(
324 AdaptiveRuntimeSelector::select_runtime(&medium),
325 RuntimeType::Async
326 );
327
328 let high = SystemResources {
330 cpu_cores: 8,
331 cpu_threads: 16,
332 total_memory_mb: 16384,
333 available_memory_mb: 8192,
334 };
335 assert_eq!(
336 AdaptiveRuntimeSelector::select_runtime(&high),
337 RuntimeType::Actor
338 );
339 }
340
341 #[test]
342 fn test_calc_queue_size() {
343 assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(2048), 500);
345
346 assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(4096), 500);
348
349 assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(8192), 800);
351
352 assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(16384), 1600);
354
355 assert_eq!(AdaptiveRuntimeSelector::calc_queue_size(128 * 1024), 10000);
357 }
358
359 #[test]
360 fn test_generate_config() {
361 let resources = SystemResources {
362 cpu_cores: 4,
363 cpu_threads: 8,
364 total_memory_mb: 8192,
365 available_memory_mb: 4096,
366 };
367
368 let config = AdaptiveRuntimeSelector::generate_config(&resources);
369
370 assert_eq!(config.runtime.runtime_type, RuntimeType::Async);
372
373 assert_eq!(config.processor.max_concurrent_tasks, 6);
375
376 assert_eq!(config.processor.max_queue_size, 500);
378
379 assert_eq!(config.performance.middleware_timeout_ms, 500);
381 }
382
383 #[test]
384 fn test_concurrent_tasks_calculation() {
385 let low = SystemResources {
387 cpu_cores: 1,
388 cpu_threads: 1,
389 total_memory_mb: 2048,
390 available_memory_mb: 1024,
391 };
392 let config = AdaptiveRuntimeSelector::generate_config(&low);
393 assert!(
394 config.processor.max_concurrent_tasks >= 2,
395 "并发数应该至少为2"
396 );
397
398 let medium = SystemResources {
400 cpu_cores: 4,
401 cpu_threads: 8,
402 total_memory_mb: 8192,
403 available_memory_mb: 4096,
404 };
405 let config = AdaptiveRuntimeSelector::generate_config(&medium);
406 assert_eq!(config.processor.max_concurrent_tasks, 6, "8 * 0.75 = 6");
407 }
408}