|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use std::time::Duration; |
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
|
|
pub enum Tier { |
|
|
|
|
|
Hot, |
|
|
|
|
|
Warm, |
|
|
|
|
|
Cold, |
|
|
} |
|
|
|
|
|
impl Tier { |
|
|
|
|
|
pub fn expected_latency(&self) -> (Duration, Duration) { |
|
|
match self { |
|
|
Tier::Hot => (Duration::from_micros(1), Duration::from_millis(1)), |
|
|
Tier::Warm => (Duration::from_millis(1), Duration::from_millis(10)), |
|
|
Tier::Cold => (Duration::from_millis(10), Duration::from_millis(100)), |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)] |
|
|
pub struct LatencyMeasurement { |
|
|
|
|
|
pub tier: Tier, |
|
|
|
|
|
|
|
|
pub latency: Duration, |
|
|
|
|
|
|
|
|
pub throughput_ops: Option<f64>, |
|
|
|
|
|
|
|
|
pub measured_at: std::time::Instant, |
|
|
} |
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)] |
|
|
pub struct LatencyBudget { |
|
|
|
|
|
pub total: Duration, |
|
|
|
|
|
|
|
|
pub per_operation: Duration, |
|
|
|
|
|
|
|
|
pub max_operations: usize, |
|
|
} |
|
|
|
|
|
impl Default for LatencyBudget { |
|
|
fn default() -> Self { |
|
|
Self { |
|
|
total: Duration::from_millis(50), |
|
|
per_operation: Duration::from_millis(5), |
|
|
max_operations: 10, |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)] |
|
|
pub struct TierStats { |
|
|
|
|
|
pub tier: Tier, |
|
|
|
|
|
|
|
|
pub count: usize, |
|
|
|
|
|
|
|
|
pub size_bytes: usize, |
|
|
|
|
|
|
|
|
pub capacity_bytes: usize, |
|
|
|
|
|
|
|
|
pub usage_ratio: f32, |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub trait Latency: Send + Sync { |
|
|
|
|
|
|
|
|
|
|
|
fn probe(&mut self, tier: Tier) -> LatencyMeasurement; |
|
|
|
|
|
|
|
|
fn budget(&self) -> LatencyBudget; |
|
|
|
|
|
|
|
|
fn set_budget(&mut self, budget: LatencyBudget); |
|
|
|
|
|
|
|
|
fn available_capacity(&self, tier: Tier) -> usize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn recommend_tier(&self, expected_accesses: u32) -> Tier; |
|
|
|
|
|
|
|
|
fn tier_stats(&self, tier: Tier) -> TierStats; |
|
|
|
|
|
|
|
|
fn all_stats(&self) -> Vec<TierStats> { |
|
|
vec![ |
|
|
self.tier_stats(Tier::Hot), |
|
|
self.tier_stats(Tier::Warm), |
|
|
self.tier_stats(Tier::Cold), |
|
|
] |
|
|
} |
|
|
} |
|
|
|