use std::collections::{HashMap, VecDeque};
use std::sync::{Arc, RwLock};
use std::time::Instant;
#[derive(Debug)]
pub struct MemoryManager {
usage_tracker: MemoryUsageTracker,
gc_policies: HashMap<String, super::gc_policy::GcPolicy>,
pressure_monitor: super::memory_pressure::MemoryPressureMonitor,
}
#[derive(Debug)]
pub struct MemoryUsageTracker {
current_usage: Arc<RwLock<usize>>,
pub peak_usage: usize,
usage_history: VecDeque<MemoryUsagePoint>,
max_history: usize,
}
#[derive(Debug, Clone)]
pub struct MemoryUsagePoint {
pub timestamp: Instant,
pub usage: usize,
pub allocations: usize,
}
#[derive(Debug, Clone)]
pub struct MemoryStats {
pub current_usage: usize,
pub peak_usage: usize,
pub pressure_level: super::memory_pressure::MemoryPressureLevel,
pub gc_runs: usize,
}
impl MemoryManager {
pub fn new() -> Self {
Self {
usage_tracker: MemoryUsageTracker::new(),
gc_policies: HashMap::new(),
pressure_monitor: super::memory_pressure::MemoryPressureMonitor::new(),
}
}
pub fn collect_garbage(&self) -> crate::diagnostics::Result<usize> {
let collected = 1024;
Ok(collected)
}
pub fn current_usage(&self) -> usize {
*self.usage_tracker.current_usage.read().unwrap()
}
pub fn get_memory_stats(&self) -> MemoryStats {
MemoryStats {
current_usage: self.current_usage(),
peak_usage: self.usage_tracker.peak_usage,
pressure_level: self.pressure_monitor.pressure_level,
gc_runs: self.usage_tracker.usage_history.len(),
}
}
pub fn set_gc_policy(&mut self, name: String, policy: super::gc_policy::GcPolicy) {
self.gc_policies.insert(name, policy);
}
pub fn get_gc_policy(&self, name: &str) -> Option<&super::gc_policy::GcPolicy> {
self.gc_policies.get(name)
}
pub fn force_gc(&self) -> crate::diagnostics::Result<usize> {
self.collect_garbage()
}
pub fn memory_pressure(&self) -> super::memory_pressure::MemoryPressureLevel {
self.pressure_monitor.pressure_level
}
pub fn update_usage(&mut self, usage: usize) {
*self.usage_tracker.current_usage.write().unwrap() = usage;
if usage > self.usage_tracker.peak_usage {
self.usage_tracker.peak_usage = usage;
}
let point = MemoryUsagePoint {
timestamp: Instant::now(),
usage,
allocations: 0, };
if self.usage_tracker.usage_history.len() >= self.usage_tracker.max_history {
self.usage_tracker.usage_history.pop_front();
}
self.usage_tracker.usage_history.push_back(point);
}
pub fn get_usage_history(&self) -> &VecDeque<MemoryUsagePoint> {
&self.usage_tracker.usage_history
}
pub fn average_usage(&self) -> Option<f64> {
if self.usage_tracker.usage_history.is_empty() {
return None;
}
let total: usize = self.usage_tracker.usage_history.iter().map(|p| p.usage).sum();
Some(total as f64 / self.usage_tracker.usage_history.len() as f64)
}
pub fn clear_history(&mut self) {
self.usage_tracker.usage_history.clear();
}
}
impl Default for MemoryUsageTracker {
fn default() -> Self {
Self::new()
}
}
impl MemoryUsageTracker {
pub fn new() -> Self {
Self {
current_usage: Arc::new(RwLock::new(0)),
peak_usage: 0,
usage_history: VecDeque::new(),
max_history: 1000,
}
}
pub fn record_collection(&mut self, _collected: usize) {
let current = *self.current_usage.read().unwrap();
if current > self.peak_usage {
self.peak_usage = current;
}
let point = MemoryUsagePoint {
timestamp: Instant::now(),
usage: current,
allocations: 0, };
if self.usage_history.len() >= self.max_history {
self.usage_history.pop_front();
}
self.usage_history.push_back(point);
}
pub fn current(&self) -> usize {
*self.current_usage.read().unwrap()
}
pub fn peak(&self) -> usize {
self.peak_usage
}
pub fn reset_peak(&mut self) {
self.peak_usage = *self.current_usage.read().unwrap();
}
}
impl MemoryUsagePoint {
pub fn new(usage: usize, allocations: usize) -> Self {
Self {
timestamp: Instant::now(),
usage,
allocations,
}
}
pub fn age(&self) -> std::time::Duration {
Instant::now() - self.timestamp
}
pub fn usage_mb(&self) -> f64 {
self.usage as f64 / (1024.0 * 1024.0)
}
pub fn usage_kb(&self) -> f64 {
self.usage as f64 / 1024.0
}
}
impl MemoryStats {
pub fn current_usage_mb(&self) -> f64 {
self.current_usage as f64 / (1024.0 * 1024.0)
}
pub fn peak_usage_mb(&self) -> f64 {
self.peak_usage as f64 / (1024.0 * 1024.0)
}
pub fn utilization_ratio(&self) -> f64 {
if self.peak_usage == 0 {
0.0
} else {
self.current_usage as f64 / self.peak_usage as f64
}
}
}
impl Default for MemoryManager {
fn default() -> Self {
Self::new()
}
}