use fulgurance::prelude::*;
fn main() {
println!("=== Fulgurance Cache Library Demo ===\n");
demo_basic_lru();
demo_fulgurance_prefetch();
demo_performance_comparison();
}
fn demo_basic_lru() {
println!("1. Basic LRU Cache Demo");
println!("-----------------------");
let mut cache = LruCache::new(3);
cache.insert(1, "one");
cache.insert(2, "two");
cache.insert(3, "three");
println!("After inserting 1,2,3:");
println!(" Cache size: {}", cache.len());
println!(" Get 1: {:?}", cache.get(&1));
println!(" Get 2: {:?}", cache.get(&2));
println!(" Get 3: {:?}", cache.get(&3));
cache.get(&1);
println!("\nAfter accessing key 1:");
cache.insert(4, "four");
println!("After inserting key 4:");
println!(" Get 1: {:?}", cache.get(&1));
println!(" Get 2: {:?} (should be evicted)", cache.get(&2));
println!(" Get 3: {:?}", cache.get(&3));
println!(" Get 4: {:?}", cache.get(&4));
println!();
}
fn demo_fulgurance_prefetch() {
println!("2. Fulgurance Cache with Prefetching Demo");
println!("------------------------------------------");
let cache = LruCache::new(10);
let prefetch = SequentialPrefetch::new();
let data_source = |key: &i32| -> Option<String> {
if *key >= 0 && *key <= 100 {
println!(" [DATA SOURCE] Loading key: {}", key);
Some(format!("data_value_{}", key))
} else {
None
}
};
let mut fulgrance = FulgranceCache::new(cache, prefetch)
.with_prefetch_fn(data_source);
println!("Accessing sequential data (should trigger prefetching):");
for i in 1..=5 {
println!(" Requesting key {}:", i);
if let Some(value) = fulgrance.get(&i) {
println!(" Got: {}", value);
}
println!(" Cache size after access: {}", fulgrance.len());
}
println!("\nCache statistics:");
let stats = fulgrance.stats();
println!(" Total accesses: {}", stats.total_accesses);
println!(" Cache hits: {}", stats.hits);
println!(" Cache misses: {}", stats.misses);
println!(" Hit ratio: {:.2}%", stats.hit_ratio() * 100.0);
println!(" Prefetch hits: {}", stats.prefetch_hits);
println!();
}
fn demo_performance_comparison() {
println!("3. Performance Comparison Demo");
println!("------------------------------");
let test_size = 1000;
let cache_size = 100;
let access_pattern: Vec<i32> = (1..=test_size).collect();
println!("Testing LRU without prefetching...");
let start = std::time::Instant::now();
let mut cache_only = LruCache::new(cache_size);
let mut hits = 0;
for &key in &access_pattern {
if cache_only.get(&key).is_some() {
hits += 1;
} else {
cache_only.insert(key, format!("value_{}", key));
}
}
let duration_no_prefetch = start.elapsed();
let hit_ratio_no_prefetch = hits as f64 / test_size as f64;
println!("Testing Fulgurance with sequential prefetching...");
let start = std::time::Instant::now();
let cache = LruCache::new(cache_size);
let prefetch = SequentialPrefetch::new();
let mut fulgrance = FulgranceCache::new(cache, prefetch)
.with_prefetch_fn(|key: &i32| Some(format!("value_{}", key)));
for &key in &access_pattern {
fulgrance.get(&key);
}
let duration_with_prefetch = start.elapsed();
let stats = fulgrance.stats();
println!("\nResults:");
println!(" LRU only:");
println!(" Time: {:?}", duration_no_prefetch);
println!(" Hit ratio: {:.2}%", hit_ratio_no_prefetch * 100.0);
println!(" Fulgurance with prefetching:");
println!(" Time: {:?}", duration_with_prefetch);
println!(" Hit ratio: {:.2}%", stats.hit_ratio() * 100.0);
println!(" Total accesses: {}", stats.total_accesses);
println!(" Cache hits: {}", stats.hits);
println!(" Prefetch hits: {}", stats.prefetch_hits);
let speedup = duration_no_prefetch.as_nanos() as f64 / duration_with_prefetch.as_nanos() as f64;
if speedup > 1.0 {
println!(" Speedup: {:.2}x faster", speedup);
} else {
println!(" Overhead: {:.2}x slower", 1.0 / speedup);
}
}