use alloc::{vec::Vec, collections::BTreeMap};
use core::mem;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
use crate::{Result, SwarmError, AgentId, RegionId, ResourceRequirements};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MemoryConfig {
pub total_size: u64,
pub region_size: u64,
pub max_regions_per_agent: usize,
pub compression_enabled: bool,
pub eviction_policy: EvictionPolicy,
}
impl Default for MemoryConfig {
fn default() -> Self {
Self {
total_size: 28 * 1024 * 1024, region_size: 64 * 1024, max_regions_per_agent: 16,
compression_enabled: true,
eviction_policy: EvictionPolicy::LRU,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum EvictionPolicy {
LRU,
LFU,
FIFO,
TTL,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RegionMetadata {
pub id: RegionId,
pub owner: AgentId,
pub size: u64,
pub created_at: u64,
pub last_accessed: u64,
pub access_count: u64,
pub locked: bool,
pub compressed: bool,
}
#[derive(Debug, Clone)]
pub struct MemoryRegion {
pub metadata: RegionMetadata,
pub data: Vec<u8>,
}
impl MemoryRegion {
fn new(owner: AgentId, size: u64) -> Self {
static mut COUNTER: u64 = 0;
let timestamp = unsafe {
COUNTER += 1;
COUNTER
};
Self {
metadata: RegionMetadata {
id: RegionId::new(),
owner,
size,
created_at: timestamp,
last_accessed: timestamp,
access_count: 0,
locked: false,
compressed: false,
},
data: Vec::with_capacity(size as usize),
}
}
pub fn read(&mut self) -> Result<&[u8]> {
if self.metadata.locked {
return Err(SwarmError::memory("Region is locked"));
}
self.update_access();
Ok(&self.data)
}
pub fn write(&mut self, data: &[u8]) -> Result<()> {
if self.metadata.locked {
return Err(SwarmError::memory("Region is locked"));
}
if data.len() > self.metadata.size as usize {
return Err(SwarmError::memory("Data exceeds region size"));
}
self.data.clear();
self.data.extend_from_slice(data);
self.update_access();
Ok(())
}
pub fn lock(&mut self) -> Result<()> {
if self.metadata.locked {
return Err(SwarmError::memory("Region already locked"));
}
self.metadata.locked = true;
Ok(())
}
pub fn unlock(&mut self) -> Result<()> {
self.metadata.locked = false;
Ok(())
}
fn update_access(&mut self) {
static mut COUNTER: u64 = 0;
self.metadata.last_accessed = unsafe {
COUNTER += 1;
COUNTER
};
self.metadata.access_count += 1;
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MemoryStats {
pub total_regions: usize,
pub allocated_regions: usize,
pub free_regions: usize,
pub total_bytes_allocated: u64,
pub compression_ratio: f32,
pub evictions: u64,
pub cache_hits: u64,
pub cache_misses: u64,
pub utilization: f32,
}
pub struct MemoryManager {
config: MemoryConfig,
regions: BTreeMap<RegionId, MemoryRegion>,
agent_allocations: BTreeMap<AgentId, Vec<RegionId>>,
free_regions: Vec<RegionId>,
stats: MemoryStats,
}
impl MemoryManager {
pub fn new(config: MemoryConfig) -> Self {
let total_regions = (config.total_size / config.region_size) as usize;
Self {
config,
regions: BTreeMap::new(),
agent_allocations: BTreeMap::new(),
free_regions: Vec::with_capacity(total_regions),
stats: MemoryStats {
total_regions,
allocated_regions: 0,
free_regions: total_regions,
total_bytes_allocated: 0,
compression_ratio: 1.0,
evictions: 0,
cache_hits: 0,
cache_misses: 0,
utilization: 0.0,
},
}
}
pub fn initialize(&mut self) -> Result<()> {
for _ in 0..self.stats.total_regions {
self.free_regions.push(RegionId::new());
}
Ok(())
}
pub fn allocate(&mut self, agent_id: AgentId, size: u64) -> Result<RegionId> {
if size > self.config.region_size {
return Err(SwarmError::memory("Requested size exceeds region size"));
}
if let Some(agent_regions) = self.agent_allocations.get(&agent_id) {
if agent_regions.len() >= self.config.max_regions_per_agent {
return Err(SwarmError::memory("Agent allocation limit reached"));
}
}
let region_id = self.free_regions.pop()
.ok_or_else(|| SwarmError::memory("No free regions available"))?;
let region = MemoryRegion::new(agent_id, self.config.region_size);
let actual_region_id = region.metadata.id;
self.regions.insert(actual_region_id, region);
self.agent_allocations
.entry(agent_id)
.or_insert_with(Vec::new)
.push(actual_region_id);
self.stats.allocated_regions += 1;
self.stats.free_regions -= 1;
self.stats.total_bytes_allocated += size;
self.update_utilization();
Ok(actual_region_id)
}
pub fn deallocate(&mut self, region_id: RegionId) -> Result<()> {
let region = self.regions.remove(®ion_id)
.ok_or_else(|| SwarmError::memory("Region not found"))?;
if let Some(agent_regions) = self.agent_allocations.get_mut(®ion.metadata.owner) {
agent_regions.retain(|&id| id != region_id);
if agent_regions.is_empty() {
self.agent_allocations.remove(®ion.metadata.owner);
}
}
self.free_regions.push(region_id);
self.stats.allocated_regions -= 1;
self.stats.free_regions += 1;
self.stats.total_bytes_allocated -= region.data.len() as u64;
self.update_utilization();
Ok(())
}
pub fn read(&mut self, region_id: RegionId) -> Result<Vec<u8>> {
let region = self.regions.get_mut(®ion_id)
.ok_or_else(|| SwarmError::memory("Region not found"))?;
let data = region.read()?;
self.stats.cache_hits += 1;
Ok(data.to_vec())
}
pub fn write(&mut self, region_id: RegionId, data: &[u8]) -> Result<()> {
let region = self.regions.get_mut(®ion_id)
.ok_or_else(|| SwarmError::memory("Region not found"))?;
region.write(data)?;
Ok(())
}
pub fn copy(&mut self, src_id: RegionId, dst_id: RegionId) -> Result<()> {
let data = {
let src_region = self.regions.get_mut(&src_id)
.ok_or_else(|| SwarmError::memory("Source region not found"))?;
src_region.read()?.to_vec()
};
let dst_region = self.regions.get_mut(&dst_id)
.ok_or_else(|| SwarmError::memory("Destination region not found"))?;
dst_region.write(&data)?;
Ok(())
}
pub fn transfer(&mut self, region_id: RegionId, new_owner: AgentId) -> Result<()> {
let region = self.regions.get_mut(®ion_id)
.ok_or_else(|| SwarmError::memory("Region not found"))?;
let old_owner = region.metadata.owner;
region.metadata.owner = new_owner;
if let Some(old_regions) = self.agent_allocations.get_mut(&old_owner) {
old_regions.retain(|&id| id != region_id);
if old_regions.is_empty() {
self.agent_allocations.remove(&old_owner);
}
}
self.agent_allocations
.entry(new_owner)
.or_insert_with(Vec::new)
.push(region_id);
Ok(())
}
pub fn lock_region(&mut self, region_id: RegionId) -> Result<()> {
let region = self.regions.get_mut(®ion_id)
.ok_or_else(|| SwarmError::memory("Region not found"))?;
region.lock()
}
pub fn unlock_region(&mut self, region_id: RegionId) -> Result<()> {
let region = self.regions.get_mut(®ion_id)
.ok_or_else(|| SwarmError::memory("Region not found"))?;
region.unlock()
}
pub fn stats(&self) -> &MemoryStats {
&self.stats
}
pub fn utilization(&self) -> f32 {
self.stats.utilization
}
pub fn garbage_collect(&mut self) -> Result<u64> {
let mut evicted = 0;
match self.config.eviction_policy {
EvictionPolicy::LRU => {
evicted += self.evict_lru()?;
}
EvictionPolicy::LFU => {
evicted += self.evict_lfu()?;
}
EvictionPolicy::FIFO => {
evicted += self.evict_fifo()?;
}
EvictionPolicy::TTL => {
evicted += self.evict_ttl()?;
}
}
self.stats.evictions += evicted;
Ok(evicted)
}
pub fn reset(&mut self) {
self.regions.clear();
self.agent_allocations.clear();
self.free_regions.clear();
for _ in 0..self.stats.total_regions {
self.free_regions.push(RegionId::new());
}
self.stats.allocated_regions = 0;
self.stats.free_regions = self.stats.total_regions;
self.stats.total_bytes_allocated = 0;
self.stats.evictions = 0;
self.stats.cache_hits = 0;
self.stats.cache_misses = 0;
self.update_utilization();
}
fn update_utilization(&mut self) {
if self.stats.total_regions > 0 {
self.stats.utilization =
(self.stats.allocated_regions as f32) / (self.stats.total_regions as f32);
} else {
self.stats.utilization = 0.0;
}
}
fn evict_lru(&mut self) -> Result<u64> {
let mut candidates: Vec<_> = self.regions.iter()
.map(|(id, region)| (*id, region.metadata.last_accessed))
.collect();
candidates.sort_by_key(|(_, last_accessed)| *last_accessed);
let to_evict = candidates.len() / 10; let mut evicted = 0;
for (region_id, _) in candidates.into_iter().take(to_evict) {
if !self.regions.get(®ion_id).unwrap().metadata.locked {
self.deallocate(region_id)?;
evicted += 1;
}
}
Ok(evicted)
}
fn evict_lfu(&mut self) -> Result<u64> {
let mut candidates: Vec<_> = self.regions.iter()
.map(|(id, region)| (*id, region.metadata.access_count))
.collect();
candidates.sort_by_key(|(_, access_count)| *access_count);
let to_evict = candidates.len() / 10; let mut evicted = 0;
for (region_id, _) in candidates.into_iter().take(to_evict) {
if !self.regions.get(®ion_id).unwrap().metadata.locked {
self.deallocate(region_id)?;
evicted += 1;
}
}
Ok(evicted)
}
fn evict_fifo(&mut self) -> Result<u64> {
let mut candidates: Vec<_> = self.regions.iter()
.map(|(id, region)| (*id, region.metadata.created_at))
.collect();
candidates.sort_by_key(|(_, created_at)| *created_at);
let to_evict = candidates.len() / 10; let mut evicted = 0;
for (region_id, _) in candidates.into_iter().take(to_evict) {
if !self.regions.get(®ion_id).unwrap().metadata.locked {
self.deallocate(region_id)?;
evicted += 1;
}
}
Ok(evicted)
}
fn evict_ttl(&mut self) -> Result<u64> {
static mut CURRENT_TIME: u64 = 0;
let current_time = unsafe {
CURRENT_TIME += 1;
CURRENT_TIME
};
let ttl_threshold = 1000; let mut evicted = 0;
let expired_regions: Vec<_> = self.regions.iter()
.filter(|(_, region)| {
current_time - region.metadata.created_at > ttl_threshold &&
!region.metadata.locked
})
.map(|(id, _)| *id)
.collect();
for region_id in expired_regions {
self.deallocate(region_id)?;
evicted += 1;
}
Ok(evicted)
}
}
pub struct VectorPool {
pool: Vec<Vec<u8>>,
config: VectorPoolConfig,
}
#[derive(Debug, Clone)]
pub struct VectorPoolConfig {
pub max_vectors: usize,
pub default_capacity: usize,
}
impl Default for VectorPoolConfig {
fn default() -> Self {
Self {
max_vectors: 1000,
default_capacity: 1024,
}
}
}
impl VectorPool {
pub fn new(config: VectorPoolConfig) -> Self {
Self {
pool: Vec::with_capacity(config.max_vectors),
config,
}
}
pub fn get(&mut self) -> Vec<u8> {
self.pool.pop().unwrap_or_else(|| {
Vec::with_capacity(self.config.default_capacity)
})
}
pub fn put(&mut self, mut vec: Vec<u8>) {
if self.pool.len() < self.config.max_vectors {
vec.clear();
self.pool.push(vec);
}
}
pub fn stats(&self) -> VectorPoolStats {
VectorPoolStats {
available_vectors: self.pool.len(),
total_capacity: self.pool.capacity(),
}
}
}
#[derive(Debug, Clone)]
pub struct VectorPoolStats {
pub available_vectors: usize,
pub total_capacity: usize,
}