scirs2_vision/ai_optimization_modules/
predictive_scaling.rs1use std::collections::VecDeque;
7use std::time::{Duration, Instant};
8
9#[derive(Debug)]
11pub struct PredictiveScaler {
12 workload_history: VecDeque<WorkloadMeasurement>,
14 model_params: PredictionModel,
16 scaling_predictions: VecDeque<ScalingPrediction>,
18 current_scaling: ScalingState,
20}
21
22#[derive(Debug, Clone)]
24pub struct WorkloadMeasurement {
25 pub timestamp: Instant,
27 pub processing_load: f64,
29 pub input_complexity: f64,
31 pub required_resources: ResourceRequirement,
33}
34
35#[derive(Debug, Clone)]
37pub struct ResourceRequirement {
38 pub cpu_cores: f64,
40 pub memory_mb: f64,
42 pub gpu_utilization: f64,
44}
45
46#[derive(Debug, Clone)]
48pub struct PredictionModel {
49 pub model_type: ModelType,
51 pub parameters: Vec<f64>,
53 pub _predictionwindow: f64,
55 pub accuracy: f64,
57}
58
59#[derive(Debug, Clone)]
61pub enum ModelType {
62 LinearRegression,
64 ARIMA {
66 p: usize,
68 d: usize,
70 q: usize,
72 },
73 NeuralNetwork {
75 hidden_layers: Vec<usize>,
77 },
78 Ensemble {
80 models: Vec<ModelType>,
82 },
83}
84
85#[derive(Debug, Clone)]
87pub struct ScalingPrediction {
88 pub horizon: Duration,
90 pub predicted_resources: ResourceRequirement,
92 pub confidence: f64,
94 pub timestamp: Instant,
96}
97
98#[derive(Debug, Clone)]
100pub struct ScalingState {
101 pub active_cores: usize,
103 pub allocated_memory: f64,
105 pub gpu_utilization: f64,
107 pub last_scaling: Instant,
109}
110
111impl PredictiveScaler {
112 pub fn new(_predictionwindow: f64) -> Self {
114 Self {
115 workload_history: VecDeque::with_capacity(10000),
116 model_params: PredictionModel {
117 model_type: ModelType::LinearRegression,
118 parameters: vec![0.0, 1.0], _predictionwindow,
120 accuracy: 0.7,
121 },
122 scaling_predictions: VecDeque::with_capacity(100),
123 current_scaling: ScalingState {
124 active_cores: 1,
125 allocated_memory: 512.0,
126 gpu_utilization: 0.0,
127 last_scaling: Instant::now(),
128 },
129 }
130 }
131
132 pub fn record_workload(&mut self, measurement: WorkloadMeasurement) {
134 self.workload_history.push_back(measurement);
135
136 if self.workload_history.len() > 10000 {
138 self.workload_history.pop_front();
139 }
140
141 if self.workload_history.len() > 100 {
143 self.update_prediction_model();
144 }
145 }
146
147 fn update_prediction_model(&mut self) {
149 match &self.model_params.model_type {
150 ModelType::LinearRegression => {
151 self.update_linear_regression();
152 }
153 ModelType::ARIMA { .. } => {
154 self.update_arima_model();
156 }
157 _ => {
158 }
160 }
161 }
162
163 fn update_linear_regression(&mut self) {
165 if self.workload_history.len() < 10 {
166 return;
167 }
168
169 let recent_data: Vec<_> = self.workload_history.iter().rev().take(100).collect();
171
172 let n = recent_data.len() as f64;
173 let mut sum_x = 0.0;
174 let mut sum_y = 0.0;
175 let mut sum_xy = 0.0;
176 let mut sum_x2 = 0.0;
177
178 for (i, measurement) in recent_data.iter().enumerate() {
179 let x = i as f64;
180 let y = measurement.processing_load;
181
182 sum_x += x;
183 sum_y += y;
184 sum_xy += x * y;
185 sum_x2 += x * x;
186 }
187
188 let slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x);
190 let intercept = (sum_y - slope * sum_x) / n;
191
192 self.model_params.parameters = vec![intercept, slope];
193 }
194
195 fn update_arima_model(&mut self) {
197 }
200
201 pub fn generate_predictions(&mut self, horizons: Vec<Duration>) -> Vec<ScalingPrediction> {
203 let mut predictions = Vec::new();
204 let current_time = Instant::now();
205
206 for horizon in horizons {
207 let predictedload = self.predict_load(horizon);
208 let predicted_resources = self.load_to_resources(predictedload);
209 let confidence = self.calculate_confidence(horizon);
210
211 predictions.push(ScalingPrediction {
212 horizon,
213 predicted_resources,
214 confidence,
215 timestamp: current_time,
216 });
217 }
218
219 for prediction in &predictions {
221 self.scaling_predictions.push_back(prediction.clone());
222 }
223
224 if self.scaling_predictions.len() > 100 {
226 self.scaling_predictions.pop_front();
227 }
228
229 predictions
230 }
231
232 fn predict_load(&self, horizon: Duration) -> f64 {
234 let horizon_secs = horizon.as_secs_f64();
235
236 match &self.model_params.model_type {
237 ModelType::LinearRegression => {
238 let intercept = self.model_params.parameters[0];
239 let slope = self.model_params.parameters[1];
240
241 let current_index = self.workload_history.len() as f64;
243 let future_index = current_index + horizon_secs / 60.0; (intercept + slope * future_index).clamp(0.0, 1.0)
246 }
247 _ => {
248 self.workload_history
250 .back()
251 .map(|m| m.processing_load)
252 .unwrap_or(0.5)
253 }
254 }
255 }
256
257 fn load_to_resources(&self, predictedload: f64) -> ResourceRequirement {
259 ResourceRequirement {
260 cpu_cores: (predictedload * 8.0).ceil(), memory_mb: 512.0 + predictedload * 1536.0, gpu_utilization: (predictedload * 0.8).min(1.0), }
264 }
265
266 fn calculate_confidence(&self, horizon: Duration) -> f64 {
268 let base_confidence = self.model_params.accuracy;
269 let horizon_penalty = (horizon.as_secs_f64() / 3600.0) * 0.1; (base_confidence - horizon_penalty).max(0.1)
272 }
273
274 pub fn get_scaling_recommendations(&self) -> Vec<ScalingRecommendation> {
276 let mut recommendations = Vec::new();
277
278 if let Some(latest_prediction) = self.scaling_predictions.back() {
279 let current_resources = &self.current_scaling;
280 let predicted_resources = &latest_prediction.predicted_resources;
281
282 if predicted_resources.cpu_cores > current_resources.active_cores as f64 + 1.0 {
284 recommendations.push(ScalingRecommendation {
285 resource_type: ResourceType::CPU,
286 action_: ScalingAction::ScaleUp,
287 magnitude: (predicted_resources.cpu_cores
288 - current_resources.active_cores as f64)
289 as usize,
290 confidence: latest_prediction.confidence,
291 reason: "Predicted CPU demand increase".to_string(),
292 });
293 } else if predicted_resources.cpu_cores < current_resources.active_cores as f64 - 1.0 {
294 recommendations.push(ScalingRecommendation {
295 resource_type: ResourceType::CPU,
296 action_: ScalingAction::ScaleDown,
297 magnitude: (current_resources.active_cores as f64
298 - predicted_resources.cpu_cores) as usize,
299 confidence: latest_prediction.confidence,
300 reason: "Predicted CPU demand decrease".to_string(),
301 });
302 }
303
304 if predicted_resources.memory_mb > current_resources.allocated_memory * 1.2 {
306 recommendations.push(ScalingRecommendation {
307 resource_type: ResourceType::Memory,
308 action_: ScalingAction::ScaleUp,
309 magnitude: (predicted_resources.memory_mb - current_resources.allocated_memory)
310 as usize,
311 confidence: latest_prediction.confidence,
312 reason: "Predicted memory demand increase".to_string(),
313 });
314 }
315 }
316
317 recommendations
318 }
319}
320
321#[derive(Debug, Clone)]
323pub struct ScalingRecommendation {
324 pub resource_type: ResourceType,
326 pub action_: ScalingAction,
328 pub magnitude: usize,
330 pub confidence: f64,
332 pub reason: String,
334}
335
336#[derive(Debug, Clone)]
338pub enum ResourceType {
339 CPU,
341 Memory,
343 GPU,
345 Network,
347}
348
349#[derive(Debug, Clone)]
351pub enum ScalingAction {
352 ScaleUp,
354 ScaleDown,
356 Maintain,
358}