use std::time::Duration;
#[derive(Debug, Clone)]
pub struct GcPolicy {
pub name: String,
pub threshold: usize,
pub generation_thresholds: Vec<usize>,
pub frequency: GcFrequency,
pub strategy: GcStrategy,
}
#[derive(Debug, Clone)]
pub enum GcFrequency {
Manual,
Periodic(Duration),
Threshold(usize),
Adaptive,
}
#[derive(Debug, Clone, PartialEq)]
pub enum GcStrategy {
MarkAndSweep,
Generational,
Incremental,
Concurrent,
}
impl GcPolicy {
pub fn new(name: String, strategy: GcStrategy) -> Self {
Self {
name,
threshold: 1024 * 1024, generation_thresholds: vec![1024 * 64, 1024 * 256, 1024 * 1024], frequency: GcFrequency::Threshold(1024 * 1024),
strategy,
}
}
pub fn manual(name: String) -> Self {
Self {
name,
threshold: usize::MAX, generation_thresholds: Vec::new(),
frequency: GcFrequency::Manual,
strategy: GcStrategy::MarkAndSweep,
}
}
pub fn periodic(name: String, interval: Duration) -> Self {
Self {
name,
threshold: usize::MAX,
generation_thresholds: Vec::new(),
frequency: GcFrequency::Periodic(interval),
strategy: GcStrategy::MarkAndSweep,
}
}
pub fn threshold(name: String, threshold: usize, strategy: GcStrategy) -> Self {
Self {
name,
threshold,
generation_thresholds: Vec::new(),
frequency: GcFrequency::Threshold(threshold),
strategy,
}
}
pub fn generational(name: String, thresholds: Vec<usize>) -> Self {
Self {
name,
threshold: thresholds.first().copied().unwrap_or(1024 * 64),
generation_thresholds: thresholds,
frequency: GcFrequency::Threshold(1024 * 64),
strategy: GcStrategy::Generational,
}
}
pub fn adaptive(name: String) -> Self {
Self {
name,
threshold: 1024 * 256, generation_thresholds: vec![1024 * 32, 1024 * 128, 1024 * 512],
frequency: GcFrequency::Adaptive,
strategy: GcStrategy::Incremental,
}
}
pub fn with_threshold(mut self, threshold: usize) -> Self {
self.threshold = threshold;
self
}
pub fn with_frequency(mut self, frequency: GcFrequency) -> Self {
self.frequency = frequency;
self
}
pub fn with_strategy(mut self, strategy: GcStrategy) -> Self {
self.strategy = strategy;
self
}
pub fn with_generations(mut self, thresholds: Vec<usize>) -> Self {
self.generation_thresholds = thresholds;
self
}
pub fn should_collect(&self, current_usage: usize) -> bool {
match &self.frequency {
GcFrequency::Manual => false,
GcFrequency::Threshold(threshold) => current_usage >= *threshold,
GcFrequency::Periodic(_) => false, GcFrequency::Adaptive => current_usage >= self.threshold,
}
}
pub fn collection_priority(&self, current_usage: usize) -> CollectionPriority {
if current_usage >= self.threshold * 2 {
CollectionPriority::Critical
} else if current_usage >= self.threshold {
CollectionPriority::High
} else if current_usage >= self.threshold / 2 {
CollectionPriority::Medium
} else {
CollectionPriority::Low
}
}
pub fn is_generational(&self) -> bool {
self.strategy == GcStrategy::Generational && !self.generation_thresholds.is_empty()
}
pub fn generation_for_age(&self, age: Duration) -> usize {
if !self.is_generational() {
return 0;
}
let age_ms = age.as_millis() as usize;
for (generation, &threshold) in self.generation_thresholds.iter().enumerate() {
if age_ms < threshold {
return generation;
}
}
self.generation_thresholds.len() }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum CollectionPriority {
Low,
Medium,
High,
Critical,
}
impl GcFrequency {
pub fn interval(&self) -> Option<Duration> {
match self {
GcFrequency::Periodic(duration) => Some(*duration),
_ => None,
}
}
pub fn is_manual(&self) -> bool {
matches!(self, GcFrequency::Manual)
}
pub fn is_adaptive(&self) -> bool {
matches!(self, GcFrequency::Adaptive)
}
}
impl GcStrategy {
pub fn supports_concurrent(&self) -> bool {
matches!(self, GcStrategy::Concurrent | GcStrategy::Incremental)
}
pub fn is_generational(&self) -> bool {
matches!(self, GcStrategy::Generational)
}
pub fn typical_pause_time(&self) -> Duration {
match self {
GcStrategy::MarkAndSweep => Duration::from_millis(10),
GcStrategy::Generational => Duration::from_millis(5),
GcStrategy::Incremental => Duration::from_millis(2),
GcStrategy::Concurrent => Duration::from_millis(1),
}
}
pub fn memory_overhead(&self) -> f64 {
match self {
GcStrategy::MarkAndSweep => 0.1, GcStrategy::Generational => 0.15, GcStrategy::Incremental => 0.2, GcStrategy::Concurrent => 0.25, }
}
}
impl Default for GcPolicy {
fn default() -> Self {
Self::new("default".to_string(), GcStrategy::MarkAndSweep)
}
}
impl CollectionPriority {
pub fn score(&self) -> u8 {
match self {
CollectionPriority::Low => 1,
CollectionPriority::Medium => 2,
CollectionPriority::High => 3,
CollectionPriority::Critical => 4,
}
}
pub fn from_usage_ratio(ratio: f64) -> Self {
if ratio >= 0.9 {
CollectionPriority::Critical
} else if ratio >= 0.7 {
CollectionPriority::High
} else if ratio >= 0.5 {
CollectionPriority::Medium
} else {
CollectionPriority::Low
}
}
}