use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex};
use std::fs::File;
use std::time::{Duration, Instant};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::atomic::AtomicU64;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MemoryMapType {
ReadOnly,
WriteOnly,
ReadWrite,
Shared,
Private,
}
#[derive(Debug, Clone)]
pub struct MemoryMapperConfig {
pub default_map_size: usize,
pub max_map_size: usize,
pub map_timeout: Duration,
pub enable_read_ahead: bool,
pub read_ahead_size: usize,
pub enable_huge_pages: bool,
}
impl Default for MemoryMapperConfig {
fn default() -> Self {
Self {
default_map_size: 4096,
max_map_size: 1024 * 1024 * 1024, map_timeout: Duration::from_secs(30),
enable_read_ahead: true,
read_ahead_size: 128 * 1024,
enable_huge_pages: false,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct MemoryMapperStats {
pub total_mapped_bytes: u64,
pub total_maps: u64,
pub success_maps: u64,
pub failed_maps: u64,
pub total_unmaps: u64,
pub avg_map_speed: f64,
pub peak_map_speed: f64,
pub access_speed_improvement: f64,
pub memory_copy_saved: u64,
}
#[derive(Debug, Clone)]
pub struct MemoryMappedRegion {
pub id: u64,
pub addr: *mut u8,
pub size: usize,
pub map_type: MemoryMapType,
pub file_path: Option<String>,
pub created_at: Instant,
pub last_accessed: Instant,
pub access_count: u64,
}
#[derive(Debug)]
pub struct MemoryMapper {
config: MemoryMapperConfig,
active_regions: Arc<Mutex<HashMap<u64, MemoryMappedRegion>>>,
stats: Arc<Mutex<MemoryMapperStats>>,
next_region_id: Arc<std::sync::atomic::AtomicU64>,
total_mapped_memory: Arc<std::sync::atomic::AtomicUsize>,
}
impl MemoryMapper {
pub fn new(config: Option<MemoryMapperConfig>) -> io::Result<Self> {
let config: _ = config.unwrap_or_default();
Ok(Self {
config,
active_regions: Arc::new(Mutex::new(HashMap::new())),
stats: Arc::new(Mutex::new(MemoryMapperStats::default())),
next_region_id: Arc::new(Mutex::new(std::sync::atomic::AtomicU64::new(1))),
total_mapped_memory: Arc::new(Mutex::new(std::sync::atomic::AtomicUsize::new(0))),
})
}
pub fn map_file(
&self,
file_path: &str,
map_type: MemoryMapType,
size: usize,
) -> io::Result<u64> {
let start_time: _ = Instant::now();
let file: _ = File::open(file_path)?;
let file_size: _ = file.metadata()?.len() as usize;
let map_size: _ = if size == 0 {
file_size
} else {
std::cmp::min(size, file_size)
};
if map_size > self.config.max_map_size {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("映射大小 {} 超过最大限制 {}", map_size, self.config.max_map_size),
));
}
let region_id: _ = self.perform_mmap(&file, map_type, map_size, Some(file_path.to_string()))?;
let elapsed: _ = start_time.elapsed();
self.update_stats_on_success(map_size, &elapsed);
println!(
"✅ 文件映射成功: {}, 大小: {} bytes, 耗时: {:?}",
file_path, map_size, elapsed
);
Ok(region_id)
}
pub fn map_anonymous(&self, map_type: MemoryMapType, size: usize) -> io::Result<u64> {
let start_time: _ = Instant::now();
if size > self.config.max_map_size {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("映射大小 {} 超过最大限制 {}", size, self.config.max_map_size),
));
}
let region_id: _ = self.perform_mmap(&std::fs::File::open("/dev/null")?, map_type, size, None)?;
let elapsed: _ = start_time.elapsed();
self.update_stats_on_success(size, &elapsed);
println!(
"✅ 匿名映射成功, 大小: {} bytes, 耗时: {:?}",
size, elapsed
);
Ok(region_id)
}
fn perform_mmap(
&self,
file: &File,
map_type: MemoryMapType,
size: usize,
file_path: Option<String>,
) -> io::Result<u64> {
let region_id: _ = self.next_region_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let (prot, flags) = match map_type {
MemoryMapType::ReadOnly => (libc::PROT_READ, libc::MAP_PRIVATE),
MemoryMapType::WriteOnly => (libc::PROT_WRITE, libc::MAP_PRIVATE),
MemoryMapType::ReadWrite => (libc::PROT_READ | libc::PROT_WRITE, libc::MAP_PRIVATE),
MemoryMapType::Shared => (libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED),
MemoryMapType::Private => (libc::PROT_READ | libc::PROT_WRITE, libc::MAP_PRIVATE),
};
#[cfg(unix)]
let flags: _ = if self.config.enable_huge_pages {
#[cfg(target_os = "linux")]
let flags: _ = flags | libc::MAP_HUGETLB;
#[cfg(not(target_os = "linux"))]
let flags: _ = flags; flags
} else {
flags
};
#[cfg(not(unix))]
let flags: _ = flags; let addr: _ = unsafe {
libc::mmap(
std::ptr::null_mut(),
size,
prot,
flags,
file.as_raw_fd(),
0,
)
};
if addr == libc::MAP_FAILED {
return Err(io::Error::last_os_error());
}
let region: _ = MemoryMappedRegion {
id: region_id,
addr: addr as *mut u8,
size,
map_type,
file_path,
created_at: Instant::now(),
last_accessed: Instant::now(),
access_count: 0,
};
{
let mut regions = self.active_regions.lock().unwrap();
regions.insert(region_id, region);
}
self.total_mapped_memory.fetch_add(size, std::sync::atomic::Ordering::Relaxed);
{
let mut stats = self.stats.lock().unwrap();
stats.total_maps += 1;
stats.success_maps += 1;
stats.total_mapped_bytes += size as u64;
}
Ok(region_id)
}
pub fn unmap_region(&self, region_id: u64) -> io::Result<()> {
let mut regions = self.active_regions.lock().unwrap();
if let Some(region) = regions.remove(®ion_id) {
let result: _ = unsafe {
libc::munmap(region.addr as *mut libc::c_void, region.size)
};
if result != 0 {
return Err(io::Error::last_os_error());
}
self.total_mapped_memory.fetch_sub(region.size, std::sync::atomic::Ordering::Relaxed);
{
let mut stats = self.stats.lock().unwrap();
stats.total_unmaps += 1;
}
println!("✅ 取消映射成功: ID {}, 大小: {} bytes", region_id, region.size);
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("未找到映射区域: {}", region_id),
))
}
}
pub fn get_region_ptr(&self, region_id: u64) -> io::Result<*mut u8> {
let regions: _ = self.active_regions.lock().unwrap();
if let Some(region_ref) = regions.get(®ion_id) {
let mut region = region_ref.clone();
region.last_accessed = Instant::now();
region.access_count += 1;
Ok(region.addr)
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("未找到映射区域: {}", region_id),
))
}
}
pub fn read_region(&self, region_id: u64, offset: usize, size: usize) -> io::Result<Vec<u8>> {
let regions: _ = self.active_regions.lock().unwrap();
if let Some(region_ref) = regions.get(®ion_id) {
if offset + size > region_ref.size {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"读取范围超出映射区域",
));
}
let ptr: _ = unsafe { region_ref.addr.add(offset) };
let data: _ = unsafe { std::slice::from_raw_parts(ptr, size) };
{
let mut region = region_ref.clone();
region.last_accessed = Instant::now();
region.access_count += 1;
}
Ok(data.to_vec())
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("未找到映射区域: {}", region_id),
))
}
}
pub fn active_region_count(&self) -> usize {
self.active_regions.lock().unwrap().len()
}
pub fn total_mapped_memory_size(&self) -> usize {
self.total_mapped_memory.load(std::sync::atomic::Ordering::Relaxed)
}
pub fn get_stats(&self) -> MemoryMapperStats {
self.stats.lock().unwrap().clone()
}
fn update_stats_on_success(&self, size: usize, elapsed: &Duration) {
let mut stats = self.stats.lock().unwrap();
if elapsed.as_secs_f64() > 0.0 {
let speed_mb: _ = size as f64 / 1024.0 / 1024.0 / elapsed.as_secs_f64();
if stats.total_maps == 1 {
stats.avg_map_speed = speed_mb;
} else {
stats.avg_map_speed = (stats.avg_map_speed * (stats.total_maps - 1) as f64 + speed_mb)
/ stats.total_maps as f64;
}
if speed_mb > stats.peak_map_speed {
stats.peak_map_speed = speed_mb;
}
}
stats.memory_copy_saved += size as u64 * 3;
stats.access_speed_improvement = stats.avg_map_speed / 100.0;
}
pub fn generate_report(&self) -> String {
let stats: _ = self.stats.lock().unwrap();
let active_count: _ = self.active_region_count();
let total_memory: _ = self.total_mapped_memory_size();
format!(
r#"
内存映射管理器性能报告
=======================
总映射次数: {}
成功映射次数: {}
失败映射次数: {}
成功率: {:.1}%
总映射字节数: {} bytes ({:.2} MB)
总取消映射次数: {}
活跃映射区域数: {}
当前映射内存: {} bytes ({:.2} MB)
平均映射速度: {:.2} MB/sec
峰值映射速度: {:.2} MB/sec
内存访问速度提升: {:.2}x
内存拷贝节省量: {} bytes ({:.2} MB)
"#,
stats.total_maps,
stats.success_maps,
stats.failed_maps,
if stats.total_maps > 0 {
stats.success_maps as f64 / stats.total_maps as f64 * 100.0
} else {
0.0
},
stats.total_mapped_bytes,
stats.total_mapped_bytes as f64 / 1024.0 / 1024.0,
stats.total_unmaps,
active_count,
total_memory,
total_memory as f64 / 1024.0 / 1024.0,
stats.avg_map_speed,
stats.peak_map_speed,
stats.access_speed_improvement,
stats.memory_copy_saved,
stats.memory_copy_saved as f64 / 1024.0 / 1024.0
)
}
pub fn cleanup_all(&self) {
let region_ids: Vec<u64> = {
let regions: _ = self.active_regions.lock().unwrap();
regions.keys().cloned().collect()
};
for region_id in region_ids {
let _: _ = self.unmap_region(region_id);
}
println!("🧹 清理所有内存映射区域");
}
}
impl Drop for MemoryMapper {
fn drop(&mut self) {
self.cleanup_all();
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_memory_mapper_creation() {
let mapper: _ = MemoryMapper::new(None).expect("创建内存映射管理器失败");
let stats: _ = mapper.get_stats();
assert_eq!(stats.total_maps, 0);
assert_eq!(stats.success_maps, 0);
assert_eq!(stats.failed_maps, 0);
println!("✅ 测试通过: 内存映射管理器创建");
}
#[test]
fn test_anonymous_mapping() {
let mapper: _ = MemoryMapper::new(None).expect("创建内存映射管理器失败");
let region_id: _ = mapper
.map_anonymous(MemoryMapType::ReadWrite, 4096)
.expect("创建匿名映射失败");
assert!(region_id > 0);
assert_eq!(mapper.active_region_count(), 1);
let _: _ = mapper.unmap_region(region_id);
println!("✅ 测试通过: 匿名内存映射");
}
#[test]
fn test_file_mapping() {
let test_file_path: _ = "/tmp/amberjs_memory_map_test.bin";
let test_data: _ = vec![42u8; 1024];
std::fs::write(test_file_path, &test_data).expect("写入测试文件失败");
let mapper: _ = MemoryMapper::new(None).expect("创建内存映射管理器失败");
let region_id: _ = mapper
.map_file(test_file_path, MemoryMapType::ReadOnly, 0)
.expect("创建文件映射失败");
assert!(region_id > 0);
assert_eq!(mapper.active_region_count(), 1);
let _: _ = mapper.unmap_region(region_id);
std::fs::remove_file(test_file_path).ok();
println!("✅ 测试通过: 文件映射");
}
#[test]
fn test_read_mapped_data() {
let test_file_path: _ = "/tmp/amberjs_memory_map_read_test.bin";
let test_data: _ = vec![1, 2, 3, 4, 5];
std::fs::write(test_file_path, &test_data).expect("写入测试文件失败");
let mapper: _ = MemoryMapper::new(None).expect("创建内存映射管理器失败");
let region_id: _ = mapper
.map_file(test_file_path, MemoryMapType::ReadOnly, 0)
.expect("创建文件映射失败");
let read_data: _ = mapper.read_region(region_id, 0, 5).expect("读取数据失败");
assert_eq!(read_data, test_data);
let _: _ = mapper.unmap_region(region_id);
std::fs::remove_file(test_file_path).ok();
println!("✅ 测试通过: 读取映射数据");
}
}