use crate::PrefetchStrategy;
pub mod sequential;
pub mod markov;
pub mod stride;
pub mod history_based;
pub mod adaptive;
pub use sequential::SequentialPrefetch;
pub use markov::MarkovPrefetch;
pub use stride::StridePrefetch;
pub use history_based::HistoryBasedPrefetch;
pub use adaptive::AdaptivePrefetch;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PrefetchType {
Sequential,
Markov,
Stride,
HistoryBased,
Adaptive,
None,
}
impl PrefetchType {
pub fn name(&self) -> &'static str {
match self {
PrefetchType::Sequential => "Sequential",
PrefetchType::Markov => "Markov",
PrefetchType::Stride => "Stride",
PrefetchType::HistoryBased => "HistoryBased",
PrefetchType::Adaptive => "Adaptive",
PrefetchType::None => "None",
}
}
pub fn description(&self) -> &'static str {
match self {
PrefetchType::Sequential => "Predicts sequential access patterns with stride detection",
PrefetchType::Markov => "Predicts with Markov chain access patterns",
PrefetchType::Stride => "Detects and predicts multiple stride patterns simultaneously",
PrefetchType::HistoryBased => "Learns from historical access sequences (n-grams)",
PrefetchType::Adaptive => "Dynamically combines multiple strategies with performance weighting",
PrefetchType::None => "No prefetching - baseline strategy",
}
}
pub fn all() -> &'static [PrefetchType] {
&[
PrefetchType::Sequential,
PrefetchType::Markov,
PrefetchType::Stride,
PrefetchType::HistoryBased,
PrefetchType::Adaptive,
PrefetchType::None,
]
}
}
#[derive(Debug, Clone, Default)]
pub struct NoPrefetch;
impl<K> PrefetchStrategy<K> for NoPrefetch {
fn predict_next(&mut self, _accessed_key: &K) -> Vec<K> {
Vec::new()
}
fn update_access_pattern(&mut self, _key: &K) {}
fn reset(&mut self) {}
}
pub fn create_prefetch_strategy_i32(prefetch_type: PrefetchType) -> Box<dyn PrefetchStrategy<i32>> {
match prefetch_type {
PrefetchType::Sequential => Box::new(SequentialPrefetch::<i32>::new()),
PrefetchType::Markov => Box::new(MarkovPrefetch::<i32>::new()),
PrefetchType::Stride => Box::new(StridePrefetch::<i32>::new()),
PrefetchType::HistoryBased => Box::new(HistoryBasedPrefetch::<i32>::new()),
PrefetchType::Adaptive => Box::new(AdaptivePrefetch::<i32>::new()),
PrefetchType::None => Box::new(NoPrefetch),
}
}
pub fn create_prefetch_strategy_i64(prefetch_type: PrefetchType) -> Box<dyn PrefetchStrategy<i64>> {
match prefetch_type {
PrefetchType::Sequential => Box::new(SequentialPrefetch::<i64>::new()),
PrefetchType::Markov => Box::new(MarkovPrefetch::<i64>::new()),
PrefetchType::Stride => Box::new(StridePrefetch::<i64>::new()),
PrefetchType::HistoryBased => Box::new(HistoryBasedPrefetch::<i64>::new()),
PrefetchType::Adaptive => Box::new(AdaptivePrefetch::<i64>::new()),
PrefetchType::None => Box::new(NoPrefetch),
}
}
pub fn create_prefetch_strategy_usize(prefetch_type: PrefetchType) -> Box<dyn PrefetchStrategy<usize>> {
match prefetch_type {
PrefetchType::Sequential => Box::new(SequentialPrefetch::<usize>::new()),
PrefetchType::Markov => Box::new(MarkovPrefetch::<usize>::new()),
PrefetchType::Stride => Box::new(StridePrefetch::<usize>::new()),
PrefetchType::HistoryBased => Box::new(HistoryBasedPrefetch::<usize>::new()),
PrefetchType::Adaptive => Box::new(AdaptivePrefetch::<usize>::new()),
PrefetchType::None => Box::new(NoPrefetch),
}
}
pub trait BenchmarkablePrefetch<K>: PrefetchStrategy<K>
where
K: Clone,
{
fn prefetch_type(&self) -> PrefetchType;
fn benchmark_name(&self) -> String {
format!("{}_prefetch", self.prefetch_type().name())
}
fn characteristics(&self) -> PrefetchCharacteristics {
match self.prefetch_type() {
PrefetchType::Sequential => PrefetchCharacteristics {
prediction_accuracy: "High for sequential patterns",
memory_overhead: "Low",
cpu_overhead: "Very Low",
adaptability: "Low",
best_use_case: "Sequential data access with consistent strides",
},
PrefetchType::Markov => PrefetchCharacteristics {
prediction_accuracy: "High for complex patterns",
memory_overhead: "Medium",
cpu_overhead: "Medium",
adaptability: "High",
best_use_case: "Complex non-sequential patterns with state dependencies",
},
PrefetchType::Stride => PrefetchCharacteristics {
prediction_accuracy: "High for multi-stride patterns",
memory_overhead: "Low-Medium",
cpu_overhead: "Low",
adaptability: "Medium",
best_use_case: "Multiple concurrent stride patterns",
},
PrefetchType::HistoryBased => PrefetchCharacteristics {
prediction_accuracy: "High for repeating sequences",
memory_overhead: "Medium-High",
cpu_overhead: "Medium",
adaptability: "High",
best_use_case: "Complex repeating access patterns",
},
PrefetchType::Adaptive => PrefetchCharacteristics {
prediction_accuracy: "High across various patterns",
memory_overhead: "Medium-High",
cpu_overhead: "Medium-High",
adaptability: "Very High",
best_use_case: "Mixed or changing access patterns",
},
PrefetchType::None => PrefetchCharacteristics {
prediction_accuracy: "N/A",
memory_overhead: "None",
cpu_overhead: "None",
adaptability: "N/A",
best_use_case: "Baseline comparison",
},
}
}
}
impl BenchmarkablePrefetch<i32> for NoPrefetch {
fn prefetch_type(&self) -> PrefetchType {
PrefetchType::None
}
}
impl BenchmarkablePrefetch<i64> for NoPrefetch {
fn prefetch_type(&self) -> PrefetchType {
PrefetchType::None
}
}
impl BenchmarkablePrefetch<usize> for NoPrefetch {
fn prefetch_type(&self) -> PrefetchType {
PrefetchType::None
}
}
#[derive(Debug, Clone)]
pub struct PrefetchCharacteristics {
pub prediction_accuracy: &'static str,
pub memory_overhead: &'static str,
pub cpu_overhead: &'static str,
pub adaptability: &'static str,
pub best_use_case: &'static str,
}
impl Default for PrefetchCharacteristics {
fn default() -> Self {
Self {
prediction_accuracy: "Unknown",
memory_overhead: "Unknown",
cpu_overhead: "Unknown",
adaptability: "Unknown",
best_use_case: "Unknown",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prefetch_type_properties() {
assert_eq!(PrefetchType::Sequential.name(), "Sequential");
assert_eq!(PrefetchType::Markov.name(), "Markov");
assert_eq!(PrefetchType::Stride.name(), "Stride");
assert_eq!(PrefetchType::HistoryBased.name(), "HistoryBased");
assert_eq!(PrefetchType::Adaptive.name(), "Adaptive");
assert_eq!(PrefetchType::None.name(), "None");
assert!(PrefetchType::Sequential.description().contains("sequential"));
assert!(PrefetchType::Markov.description().contains("Markov"));
assert!(PrefetchType::Stride.description().contains("stride"));
assert!(PrefetchType::HistoryBased.description().contains("historical"));
assert!(PrefetchType::Adaptive.description().contains("combines"));
assert!(PrefetchType::None.description().contains("baseline"));
}
#[test]
fn test_all_prefetch_types_listed() {
let all_types = PrefetchType::all();
assert!(all_types.contains(&PrefetchType::Sequential));
assert!(all_types.contains(&PrefetchType::Markov));
assert!(all_types.contains(&PrefetchType::Stride));
assert!(all_types.contains(&PrefetchType::HistoryBased));
assert!(all_types.contains(&PrefetchType::Adaptive));
assert!(all_types.contains(&PrefetchType::None));
assert_eq!(all_types.len(), 6);
}
#[test]
fn test_no_prefetch_strategy() {
let mut strategy = NoPrefetch;
strategy.update_access_pattern(&42);
assert!(strategy.predict_next(&42).is_empty());
<NoPrefetch as PrefetchStrategy<i32>>::reset(&mut strategy);
}
#[test]
fn test_factory_creation() {
let _sequential_i32 = create_prefetch_strategy_i32(PrefetchType::Sequential);
let _markov_i32 = create_prefetch_strategy_i32(PrefetchType::Markov);
let _stride_i32 = create_prefetch_strategy_i32(PrefetchType::Stride);
let _history_i32 = create_prefetch_strategy_i32(PrefetchType::HistoryBased);
let _adaptive_i32 = create_prefetch_strategy_i32(PrefetchType::Adaptive);
let _none_i32 = create_prefetch_strategy_i32(PrefetchType::None);
let _sequential_i64 = create_prefetch_strategy_i64(PrefetchType::Sequential);
let _markov_i64 = create_prefetch_strategy_i64(PrefetchType::Markov);
let _stride_i64 = create_prefetch_strategy_i64(PrefetchType::Stride);
let _history_i64 = create_prefetch_strategy_i64(PrefetchType::HistoryBased);
let _adaptive_i64 = create_prefetch_strategy_i64(PrefetchType::Adaptive);
let _none_i64 = create_prefetch_strategy_i64(PrefetchType::None);
let _sequential_usize = create_prefetch_strategy_usize(PrefetchType::Sequential);
let _markov_usize = create_prefetch_strategy_usize(PrefetchType::Markov);
let _stride_usize = create_prefetch_strategy_usize(PrefetchType::Stride);
let _history_usize = create_prefetch_strategy_usize(PrefetchType::HistoryBased);
let _adaptive_usize = create_prefetch_strategy_usize(PrefetchType::Adaptive);
let _none_usize = create_prefetch_strategy_usize(PrefetchType::None);
}
#[test]
fn test_benchmark_characteristics() {
let sequential = SequentialPrefetch::<i32>::new();
let markov = MarkovPrefetch::<i32>::new();
let stride = StridePrefetch::<i32>::new();
let history = HistoryBasedPrefetch::<i32>::new();
let adaptive = AdaptivePrefetch::<i32>::new();
let none = NoPrefetch;
let seq_chars = sequential.characteristics();
assert_eq!(seq_chars.adaptability, "Low");
assert_eq!(seq_chars.cpu_overhead, "Very Low");
let markov_chars = markov.characteristics();
assert_eq!(markov_chars.adaptability, "High");
assert_eq!(markov_chars.cpu_overhead, "Medium");
let stride_chars = stride.characteristics();
assert_eq!(stride_chars.adaptability, "Medium");
assert_eq!(stride_chars.cpu_overhead, "Low");
let history_chars = history.characteristics();
assert_eq!(history_chars.adaptability, "High");
assert_eq!(history_chars.memory_overhead, "Medium-High");
let adaptive_chars = adaptive.characteristics();
assert_eq!(adaptive_chars.adaptability, "Very High");
assert_eq!(adaptive_chars.cpu_overhead, "Medium-High");
let none_chars = <NoPrefetch as BenchmarkablePrefetch<i32>>::characteristics(&none);
assert_eq!(none_chars.prediction_accuracy, "N/A");
assert_eq!(none_chars.memory_overhead, "None");
}
#[test]
fn test_benchmark_names() {
let sequential = SequentialPrefetch::<i32>::new();
let markov = MarkovPrefetch::<i32>::new();
let stride = StridePrefetch::<i32>::new();
let history = HistoryBasedPrefetch::<i32>::new();
let adaptive = AdaptivePrefetch::<i32>::new();
let none = NoPrefetch;
assert_eq!(sequential.benchmark_name(), "Sequential_prefetch");
assert_eq!(markov.benchmark_name(), "Markov_prefetch");
assert_eq!(stride.benchmark_name(), "Stride_prefetch");
assert_eq!(history.benchmark_name(), "HistoryBased_prefetch");
assert_eq!(adaptive.benchmark_name(), "Adaptive_prefetch");
assert_eq!(<NoPrefetch as BenchmarkablePrefetch<i32>>::benchmark_name(&none), "None_prefetch");
}
}