Skip to main content

driven/fusion/
speculative_loader.rs

1//! Speculative Template Loader
2//!
3//! AI-predicted template prefetching for instant loads.
4
5use std::collections::{HashMap, VecDeque};
6
7/// Prediction engine for template access patterns
8#[derive(Debug)]
9pub struct PredictionEngine {
10    /// Access history (template_hash -> next template hashes)
11    transitions: HashMap<u64, Vec<(u64, u32)>>,
12    /// Recent access sequence
13    history: VecDeque<u64>,
14    /// Maximum history length
15    max_history: usize,
16    /// Minimum confidence threshold
17    confidence_threshold: f32,
18}
19
20impl PredictionEngine {
21    /// Create a new prediction engine
22    pub fn new() -> Self {
23        Self {
24            transitions: HashMap::new(),
25            history: VecDeque::new(),
26            max_history: 100,
27            confidence_threshold: 0.3,
28        }
29    }
30
31    /// Record a template access
32    pub fn record_access(&mut self, template_hash: u64) {
33        // Update transitions from previous template
34        if let Some(&prev) = self.history.back() {
35            let transitions = self.transitions.entry(prev).or_default();
36
37            if let Some((_, count)) = transitions.iter_mut().find(|(h, _)| *h == template_hash) {
38                *count += 1;
39            } else {
40                transitions.push((template_hash, 1));
41            }
42        }
43
44        // Add to history
45        self.history.push_back(template_hash);
46        if self.history.len() > self.max_history {
47            self.history.pop_front();
48        }
49    }
50
51    /// Predict next templates to prefetch
52    pub fn predict(&self, current_template: u64, max_predictions: usize) -> Vec<u64> {
53        let transitions = match self.transitions.get(&current_template) {
54            Some(t) => t,
55            None => return Vec::new(),
56        };
57
58        let total: u32 = transitions.iter().map(|(_, c)| c).sum();
59        if total == 0 {
60            return Vec::new();
61        }
62
63        // Sort by count and filter by confidence
64        let mut predictions: Vec<_> = transitions
65            .iter()
66            .filter(|(_, count)| *count as f32 / total as f32 >= self.confidence_threshold)
67            .copied()
68            .collect();
69
70        predictions.sort_by(|a, b| b.1.cmp(&a.1));
71
72        predictions
73            .into_iter()
74            .take(max_predictions)
75            .map(|(hash, _)| hash)
76            .collect()
77    }
78
79    /// Get confidence for a specific transition
80    pub fn confidence(&self, from: u64, to: u64) -> f32 {
81        let transitions = match self.transitions.get(&from) {
82            Some(t) => t,
83            None => return 0.0,
84        };
85
86        let total: u32 = transitions.iter().map(|(_, c)| c).sum();
87        if total == 0 {
88            return 0.0;
89        }
90
91        transitions
92            .iter()
93            .find(|(h, _)| *h == to)
94            .map(|(_, count)| *count as f32 / total as f32)
95            .unwrap_or(0.0)
96    }
97
98    /// Clear prediction data
99    pub fn clear(&mut self) {
100        self.transitions.clear();
101        self.history.clear();
102    }
103}
104
105impl Default for PredictionEngine {
106    fn default() -> Self {
107        Self::new()
108    }
109}
110
111/// Speculative loader for prefetching templates
112#[derive(Debug)]
113pub struct SpeculativeLoader {
114    /// Prediction engine
115    prediction: PredictionEngine,
116    /// Prefetch queue
117    prefetch_queue: VecDeque<u64>,
118    /// Maximum prefetch queue size
119    max_prefetch: usize,
120    /// Templates currently being prefetched
121    in_flight: Vec<u64>,
122}
123
124impl SpeculativeLoader {
125    /// Create a new speculative loader
126    pub fn new() -> Self {
127        Self {
128            prediction: PredictionEngine::new(),
129            prefetch_queue: VecDeque::new(),
130            max_prefetch: 3,
131            in_flight: Vec::new(),
132        }
133    }
134
135    /// Record template access and trigger prefetch
136    pub fn on_access(&mut self, template_hash: u64) {
137        self.prediction.record_access(template_hash);
138
139        // Get predictions and queue for prefetch
140        let predictions = self.prediction.predict(template_hash, self.max_prefetch);
141
142        for pred in predictions {
143            if !self.prefetch_queue.contains(&pred) && !self.in_flight.contains(&pred) {
144                self.prefetch_queue.push_back(pred);
145            }
146        }
147
148        // Limit queue size
149        while self.prefetch_queue.len() > self.max_prefetch * 2 {
150            self.prefetch_queue.pop_front();
151        }
152    }
153
154    /// Get next template to prefetch
155    pub fn next_prefetch(&mut self) -> Option<u64> {
156        let hash = self.prefetch_queue.pop_front()?;
157        self.in_flight.push(hash);
158        Some(hash)
159    }
160
161    /// Mark prefetch as complete
162    pub fn prefetch_complete(&mut self, template_hash: u64) {
163        self.in_flight.retain(|&h| h != template_hash);
164    }
165
166    /// Get pending prefetch count
167    pub fn pending_count(&self) -> usize {
168        self.prefetch_queue.len() + self.in_flight.len()
169    }
170
171    /// Get prediction accuracy estimate
172    pub fn accuracy(&self) -> f32 {
173        // This would need actual hit/miss tracking
174        // Placeholder implementation
175        0.75
176    }
177}
178
179impl Default for SpeculativeLoader {
180    fn default() -> Self {
181        Self::new()
182    }
183}
184
185#[cfg(test)]
186mod tests {
187    use super::*;
188
189    #[test]
190    fn test_prediction() {
191        let mut engine = PredictionEngine::new();
192
193        // Create pattern: 1 -> 2 -> 3 -> 1 -> 2 -> 3
194        for _ in 0..10 {
195            engine.record_access(1);
196            engine.record_access(2);
197            engine.record_access(3);
198        }
199
200        // Should predict 2 after 1
201        let predictions = engine.predict(1, 1);
202        assert_eq!(predictions, vec![2]);
203
204        // Should predict 3 after 2
205        let predictions = engine.predict(2, 1);
206        assert_eq!(predictions, vec![3]);
207    }
208
209    #[test]
210    fn test_speculative_loader() {
211        let mut loader = SpeculativeLoader::new();
212
213        // Create access pattern
214        for _ in 0..5 {
215            loader.on_access(1);
216            loader.on_access(2);
217        }
218
219        // After accessing 1, should queue 2 for prefetch
220        loader.on_access(1);
221        assert!(loader.pending_count() > 0);
222    }
223}