use crate::{
BenchmarkResult, IntelligentCacheManager, PerformanceMonitor, UnifiedCache, UnifiedCacheConfig,
};
use rand::Rng;
use std::{sync::Arc, time::Duration};
use tokio::time::sleep;
#[derive(Debug, Clone)]
pub struct BenchmarkConfig {
pub operations_count: usize,
pub worker_count: usize,
pub key_space_size: usize,
pub value_size: usize,
pub read_write_ratio: f64,
pub max_duration: Duration,
}
impl Default for BenchmarkConfig {
fn default() -> Self {
Self {
operations_count: 100_000,
worker_count: 4,
key_space_size: 10_000,
value_size: 1024,
read_write_ratio: 0.8, max_duration: Duration::from_secs(60),
}
}
}
pub struct CacheBenchmarkSuite {
cache: Arc<IntelligentCacheManager<String, Vec<u8>>>,
monitor: Arc<PerformanceMonitor>,
config: BenchmarkConfig,
}
impl CacheBenchmarkSuite {
pub fn new(cache_config: UnifiedCacheConfig, bench_config: BenchmarkConfig) -> Self {
let cache = Arc::new(IntelligentCacheManager::new(cache_config));
let monitor = cache.monitor();
Self {
cache,
monitor,
config: bench_config,
}
}
pub async fn run_all_benchmarks(&self) -> Vec<BenchmarkResult> {
let mut results = Vec::new();
results.push(self.benchmark_sequential_operations().await);
results.push(self.benchmark_concurrent_operations().await);
results.push(self.benchmark_mixed_workload().await);
results.push(self.benchmark_hit_rate_optimization().await);
results.push(self.benchmark_memory_efficiency().await);
results.push(self.benchmark_predictive_preheating().await);
results.push(self.benchmark_adaptive_tuning().await);
results.push(self.benchmark_high_contention().await);
results.push(self.benchmark_large_dataset().await);
results
}
pub async fn benchmark_sequential_operations(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("sequential_operations", || async {
let test_data = self.generate_test_data();
for (key, value) in &test_data {
let _ = self.cache.put(key.clone(), value.clone()).await;
}
for (key, _) in &test_data {
let _ = self.cache.get(key).await;
}
})
.await
}
pub async fn benchmark_concurrent_operations(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("concurrent_operations", || async {
let test_data = Arc::new(self.generate_test_data());
let cache = Arc::clone(&self.cache);
let mut handles = Vec::new();
for worker_id in 0..self.config.worker_count {
let cache = Arc::clone(&cache);
let test_data = Arc::clone(&test_data);
let ops_per_worker = self.config.operations_count / self.config.worker_count;
let handle = tokio::spawn(async move {
for i in 0..ops_per_worker {
let key_index = (worker_id * ops_per_worker + i) % test_data.len();
let (key, value) = &test_data[key_index];
if i % 5 == 0 {
let _ = cache.put(key.clone(), value.clone()).await;
} else {
let _ = cache.get(key).await;
}
}
});
handles.push(handle);
}
for handle in handles {
let _ = handle.await;
}
})
.await
}
pub async fn benchmark_mixed_workload(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("mixed_workload", || async {
let test_data = self.generate_test_data();
for (i, (key, value)) in test_data.iter().enumerate() {
let operation_ratio = i as f64 / test_data.len() as f64;
if operation_ratio < self.config.read_write_ratio {
let _ = self.cache.get(key).await;
} else {
let _ = self.cache.put(key.clone(), value.clone()).await;
}
}
})
.await
}
pub async fn benchmark_hit_rate_optimization(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("hit_rate_optimization", || async {
let test_data = self.generate_test_data();
let hot_data_size = test_data.len() / 4; for (key, value) in test_data.iter().take(hot_data_size) {
let _ = self.cache.put(key.clone(), value.clone()).await;
}
for _ in 0..self.config.operations_count {
let mut rng = rand::rng();
let key_index = if rng.random::<f64>() < 0.8 {
rng.random_range(0..hot_data_size)
} else {
hot_data_size + rng.random_range(0..(test_data.len() - hot_data_size))
};
let (key, value) = &test_data[key_index];
if self.cache.get(key).await.is_none() {
let _ = self.cache.put(key.clone(), value.clone()).await;
}
}
})
.await
}
pub async fn benchmark_memory_efficiency(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("memory_efficiency", || async {
let large_value = vec![0u8; self.config.value_size * 10];
for i in 0..self.config.key_space_size {
let key = format!("large_key_{}", i);
let _ = self.cache.put(key, large_value.clone()).await;
}
for i in 0..self.config.key_space_size / 2 {
let key = format!("new_key_{}", i);
let _ = self.cache.put(key, large_value.clone()).await;
}
})
.await
}
pub async fn benchmark_predictive_preheating(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("predictive_preheating", || async {
let test_data = self.generate_test_data();
for cycle in 0..10 {
for (i, (key, value)) in test_data.iter().enumerate() {
if i % 10 == cycle % 10 {
if self.cache.get(key).await.is_none() {
let _ = self.cache.put(key.clone(), value.clone()).await;
}
}
}
sleep(Duration::from_millis(100)).await;
}
for (i, (key, _)) in test_data.iter().enumerate() {
if i % 10 == 0 {
let _ = self.cache.get(key).await;
}
}
})
.await
}
pub async fn benchmark_adaptive_tuning(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("adaptive_tuning", || async {
let test_data = self.generate_test_data();
for _ in 0..1000 {
let mut rng = rand::rng();
let key_index = rng.random_range(0..test_data.len());
let (key, value) = &test_data[key_index];
if self.cache.get(key).await.is_none() {
let _ = self.cache.put(key.clone(), value.clone()).await;
}
}
sleep(Duration::from_secs(1)).await;
let hot_keys: Vec<_> = test_data.iter().take(100).collect();
for _ in 0..1000 {
let mut rng = rand::rng();
let (key, value) = hot_keys[rng.random_range(0..hot_keys.len())];
if self.cache.get(key).await.is_none() {
let _ = self.cache.put(key.clone(), value.clone()).await;
}
}
})
.await
}
pub async fn benchmark_high_contention(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("high_contention", || async {
let hot_keys = vec!["hot_key_1", "hot_key_2", "hot_key_3"];
let test_value = vec![0u8; self.config.value_size];
let cache = Arc::clone(&self.cache);
let mut handles = Vec::new();
for _ in 0..self.config.worker_count * 2 {
let cache = Arc::clone(&cache);
let hot_keys = hot_keys.clone();
let test_value = test_value.clone();
let handle = tokio::spawn(async move {
for _ in 0..1000 {
let key_index = {
let mut rng = rand::rng();
rng.random_range(0..hot_keys.len())
};
let key = &hot_keys[key_index];
let is_read = {
let mut rng = rand::rng();
rng.random::<bool>()
};
if is_read {
let _ = cache.get(&key.to_string()).await;
} else {
let _ = cache.put(key.to_string(), test_value.clone()).await;
}
}
});
handles.push(handle);
}
for handle in handles {
let _ = handle.await;
}
})
.await
}
pub async fn benchmark_large_dataset(&self) -> BenchmarkResult {
self.monitor
.run_benchmark("large_dataset", || async {
let large_dataset_size = self.config.key_space_size * 10;
let test_value = vec![0u8; self.config.value_size];
for i in 0..large_dataset_size {
let key = format!("large_dataset_key_{}", i);
let _ = self.cache.put(key, test_value.clone()).await;
if i % 1000 == 0 {
for j in 0..100 {
let read_key = format!("large_dataset_key_{}", j);
let _ = self.cache.get(&read_key).await;
}
}
}
})
.await
}
fn generate_test_data(&self) -> Vec<(String, Vec<u8>)> {
(0..self.config.key_space_size)
.map(|i| {
let key = format!("test_key_{}", i);
let value = vec![i as u8; self.config.value_size];
(key, value)
})
.collect()
}
pub async fn get_cache_stats(&self) -> crate::UnifiedCacheStats {
self.cache.get_stats().await
}
pub async fn get_performance_metrics(&self) -> crate::PerformanceMetrics {
self.monitor.get_performance_metrics().await
}
}
pub async fn run_comprehensive_benchmarks() -> Vec<BenchmarkResult> {
println!("ð Starting Intelligent Cache Comprehensive Benchmarks");
let configs = vec![
("High Performance", UnifiedCacheConfig::high_performance()),
("Low Memory", UnifiedCacheConfig::low_memory()),
("Default", UnifiedCacheConfig::default()),
];
let mut all_results = Vec::new();
for (config_name, cache_config) in configs {
println!("\nð Testing configuration: {}", config_name);
let bench_config = BenchmarkConfig::default();
let suite = CacheBenchmarkSuite::new(cache_config, bench_config);
let results = suite.run_all_benchmarks().await;
println!(
"â
Completed {} benchmarks for {}",
results.len(),
config_name
);
for result in &results {
println!(
" {} - {:.2} ops/sec, {:.2}Ξs avg latency",
result.name, result.ops_per_second, result.avg_latency_us
);
}
all_results.extend(results);
}
println!("\nðŊ Benchmark Summary:");
println!("Total benchmarks completed: {}", all_results.len());
all_results
}