use super::SendPtr;
use anyhow::{anyhow, Result};
#[cfg(unix)]
use libc::{c_void, madvise, posix_memalign, MADV_WILLNEED};
use memmap2::{Mmap, MmapOptions};
use rand::Rng;
use std::fs::OpenOptions;
use std::ptr::NonNull;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::RwLock;
#[derive(Debug, Clone)]
pub struct DmaConfig {
pub dma_threshold: usize,
pub max_dma_buffers: usize,
pub dma_cache_size: usize,
pub alignment: usize,
}
impl Default for DmaConfig {
fn default() -> Self {
Self {
dma_threshold: 64 * 1024, max_dma_buffers: 256,
dma_cache_size: 16 * 1024 * 1024, alignment: 4096, }
}
}
#[derive(Debug, Clone)]
pub struct MmapConfig {
pub enable_prefetch: bool,
pub prefetch_pages: usize,
pub use_huge_pages: bool,
pub huge_page_size: usize,
}
impl Default for MmapConfig {
fn default() -> Self {
Self {
enable_prefetch: true,
prefetch_pages: 1024,
use_huge_pages: false,
huge_page_size: 2 * 1024 * 1024, }
}
}
#[derive(Debug, Clone)]
pub struct PrefetchConfig {
pub window_size: usize,
pub prefetch_depth: usize,
pub prefetch_latency: Duration,
pub predictive: bool,
}
impl Default for PrefetchConfig {
fn default() -> Self {
Self {
window_size: 4096,
prefetch_depth: 4,
prefetch_latency: Duration::from_nanos(100),
predictive: true,
}
}
}
#[derive(Debug)]
pub struct EnhancedZeroCopy {
dma_config: DmaConfig,
mmap_config: MmapConfig,
prefetch_config: PrefetchConfig,
dma_buffers: Arc<RwLock<Vec<DmaBuffer>>>,
mmap_cache: Arc<RwLock<lru::LruCache<String, Arc<Mmap>>>>,
prefetch_stats: Arc<PrefetchStats>,
performance_stats: Arc<PerformanceStats>,
}
#[derive(Debug)]
pub struct DmaBuffer {
pub ptr: NonNull<u8>,
pub size: usize,
pub allocated_at: Instant,
pub ref_count: Arc<AtomicUsize>,
}
unsafe impl Send for DmaBuffer {}
unsafe impl Sync for DmaBuffer {}
#[derive(Debug)]
pub struct MmapEntry {
pub mmap: Arc<Mmap>,
pub path: String,
pub size: usize,
pub access_count: AtomicUsize,
pub last_access: Instant,
}
#[derive(Debug, Default)]
pub struct PrefetchStats {
pub total_prefetches: AtomicUsize,
pub successful_prefetches: AtomicUsize,
pub cache_hits: AtomicUsize,
pub cache_misses: AtomicUsize,
}
#[derive(Debug, Default)]
pub struct PerformanceStats {
pub total_allocations: AtomicUsize,
pub total_deallocations: AtomicUsize,
pub zero_copy_operations: AtomicUsize,
pub dma_operations: AtomicUsize,
pub mmap_operations: AtomicUsize,
pub prefetch_operations: AtomicUsize,
pub bytes_saved: AtomicUsize,
pub time_saved_ms: AtomicUsize,
}
impl EnhancedZeroCopy {
pub fn new(
dma_config: DmaConfig,
mmap_config: MmapConfig,
prefetch_config: PrefetchConfig,
) -> Self {
Self {
dma_config,
mmap_config,
prefetch_config,
dma_buffers: Arc::new(RwLock::new(Vec::new())),
mmap_cache: Arc::new(RwLock::new(lru::LruCache::new(
std::num::NonZeroUsize::new(1024).unwrap(),
))),
prefetch_stats: Arc::new(PrefetchStats::default()),
performance_stats: Arc::new(PerformanceStats::default()),
}
}
pub fn default() -> Self {
Self::new(
DmaConfig::default(),
MmapConfig::default(),
PrefetchConfig::default(),
)
}
pub async fn allocate_dma(&self, size: usize) -> Result<DmaBuffer> {
if size < self.dma_config.dma_threshold {
return Err(anyhow!(
"Size {} is below DMA threshold {}",
size,
self.dma_config.dma_threshold
));
}
{
let mut buffers = self.dma_buffers.write().await;
for (idx, buffer) in buffers.iter().enumerate() {
if buffer.size >= size {
let buffer: _ = buffers.remove(idx);
self.performance_stats
.dma_operations
.fetch_add(1, Ordering::Relaxed);
return Ok(buffer);
}
}
}
let ptr: _ = self.allocate_aligned_memory(size, self.dma_config.alignment)?;
let buffer: _ = DmaBuffer {
ptr,
size,
allocated_at: Instant::now(),
ref_count: Arc::new(AtomicUsize::new(1)),
};
self.performance_stats
.dma_operations
.fetch_add(1, Ordering::Relaxed);
Ok(buffer)
}
pub async fn deallocate_dma(&self, buffer: DmaBuffer) -> Result<()> {
{
let mut buffers = self.dma_buffers.write().await;
if buffers.len() < self.dma_config.max_dma_buffers {
buffers.push(buffer);
}
}
Ok(())
}
pub async fn mmap_file(&self, path: &str, size: usize) -> Result<Arc<Mmap>> {
let mmap: _ = self.create_memory_mapping(path, size)?;
{
let mut cache = self.mmap_cache.write().await;
cache.put(path.to_string(), mmap.clone());
}
self.performance_stats
.mmap_operations
.fetch_add(1, Ordering::Relaxed);
Ok(mmap)
}
pub async fn smart_prefetch(&self, addr: SendPtr, size: usize) -> Result<()> {
if !self.mmap_config.enable_prefetch {
return Ok(());
}
self.prefetch_stats
.total_prefetches
.fetch_add(1, Ordering::Relaxed);
#[cfg(unix)]
{
unsafe {
let result: _ = madvise(addr.as_ptr() as *mut libc::c_void, size, MADV_WILLNEED);
if result == 0 {
self.prefetch_stats
.successful_prefetches
.fetch_add(1, Ordering::Relaxed);
self.performance_stats
.prefetch_operations
.fetch_add(1, Ordering::Relaxed);
Ok(())
} else {
Err(anyhow!("madvise failed with error code: {}", result))
}
}
}
#[cfg(not(unix))]
{
let _ = (addr, size);
Ok(())
}
}
pub async fn predictive_prefetch(
&self,
base_addr: SendPtr,
size: usize,
access_pattern: AccessPattern,
) -> Result<()> {
if !self.prefetch_config.predictive {
return self.smart_prefetch(base_addr, size).await;
}
match access_pattern {
AccessPattern::Sequential => {
for i in 0..self.prefetch_config.prefetch_depth {
let offset: _ = (i + 1) * self.prefetch_config.window_size;
if offset < size {
let prefetch_addr: _ =
NonNull::new(unsafe { base_addr.as_ptr().add(offset) }).unwrap();
self.smart_prefetch(
SendPtr(prefetch_addr),
self.prefetch_config.window_size,
)
.await?;
}
}
}
AccessPattern::Random => {
let mut rng = rand::rng();
for _ in 0..self.prefetch_config.prefetch_depth {
let offset: _ =
rng.random_range(0..size.saturating_sub(self.prefetch_config.window_size));
let prefetch_addr: _ =
NonNull::new(unsafe { base_addr.as_ptr().add(offset) }).unwrap();
self.smart_prefetch(SendPtr(prefetch_addr), self.prefetch_config.window_size)
.await?;
}
}
}
Ok(())
}
pub async fn zero_copy_transfer(&self, src: SendPtr, dst: SendPtr, size: usize) -> Result<()> {
if size >= self.dma_config.dma_threshold {
let _dma_buffer: _ = self.allocate_dma(size).await?;
}
unsafe {
std::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_ptr(), size);
}
self.performance_stats
.zero_copy_operations
.fetch_add(1, Ordering::Relaxed);
self.performance_stats
.bytes_saved
.fetch_add(size, Ordering::Relaxed);
Ok(())
}
pub async fn get_performance_stats(&self) -> PerformanceStatsSnapshot {
PerformanceStatsSnapshot {
total_allocations: self
.performance_stats
.total_allocations
.load(Ordering::Relaxed),
total_deallocations: self
.performance_stats
.total_deallocations
.load(Ordering::Relaxed),
zero_copy_operations: self
.performance_stats
.zero_copy_operations
.load(Ordering::Relaxed),
dma_operations: self
.performance_stats
.dma_operations
.load(Ordering::Relaxed),
mmap_operations: self
.performance_stats
.mmap_operations
.load(Ordering::Relaxed),
prefetch_operations: self
.performance_stats
.prefetch_operations
.load(Ordering::Relaxed),
bytes_saved: self.performance_stats.bytes_saved.load(Ordering::Relaxed),
time_saved_ms: self.performance_stats.time_saved_ms.load(Ordering::Relaxed),
}
}
pub async fn get_prefetch_stats(&self) -> PrefetchStatsSnapshot {
PrefetchStatsSnapshot {
total_prefetches: self.prefetch_stats.total_prefetches.load(Ordering::Relaxed),
successful_prefetches: self
.prefetch_stats
.successful_prefetches
.load(Ordering::Relaxed),
cache_hits: self.prefetch_stats.cache_hits.load(Ordering::Relaxed),
cache_misses: self.prefetch_stats.cache_misses.load(Ordering::Relaxed),
}
}
fn allocate_aligned_memory(&self, size: usize, alignment: usize) -> Result<NonNull<u8>> {
if !alignment.is_power_of_two() {
return Err(anyhow!("Alignment must be a power of two"));
}
#[cfg(unix)]
unsafe {
let mut ptr: *mut c_void = std::ptr::null_mut();
let result: _ = posix_memalign(&mut ptr, alignment, size);
if result == 0 && !ptr.is_null() {
Ok(NonNull::new_unchecked(ptr as *mut u8))
} else {
Err(anyhow!("posix_memalign failed with error code: {}", result))
}
}
#[cfg(not(unix))]
{
let layout = std::alloc::Layout::from_size_align(size, alignment)
.map_err(|e| anyhow!("invalid alignment: {e}"))?;
let ptr = unsafe { std::alloc::alloc(layout) };
NonNull::new(ptr).ok_or_else(|| anyhow!("aligned alloc returned null"))
}
}
fn create_memory_mapping(&self, path: &str, size: usize) -> Result<Arc<Mmap>> {
let file: _ = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(path)?;
file.set_len(size as u64)?;
let mmap: _ = unsafe {
let mut opts = MmapOptions::new();
opts.len(size).map(&file)?
};
Ok(Arc::new(mmap))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccessPattern {
Sequential,
Random,
}
#[derive(Debug, Clone)]
pub struct PerformanceStatsSnapshot {
pub total_allocations: usize,
pub total_deallocations: usize,
pub zero_copy_operations: usize,
pub dma_operations: usize,
pub mmap_operations: usize,
pub prefetch_operations: usize,
pub bytes_saved: usize,
pub time_saved_ms: usize,
}
#[derive(Debug, Clone)]
pub struct PrefetchStatsSnapshot {
pub total_prefetches: usize,
pub successful_prefetches: usize,
pub cache_hits: usize,
pub cache_misses: usize,
}
impl PrefetchStatsSnapshot {
pub fn success_rate(&self) -> f64 {
if self.total_prefetches == 0 {
0.0
} else {
self.successful_prefetches as f64 / self.total_prefetches as f64
}
}
pub fn cache_hit_rate(&self) -> f64 {
let total: _ = self.cache_hits + self.cache_misses;
if total == 0 {
0.0
} else {
self.cache_hits as f64 / total as f64
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_enhanced_zero_copy_creation() {
let zc: _ = EnhancedZeroCopy::default();
assert!(zc.dma_config.dma_threshold > 0);
assert!(zc.mmap_config.enable_prefetch);
}
#[tokio::test]
async fn test_performance_stats() {
let zc: _ = EnhancedZeroCopy::default();
let stats: _ = zc.get_performance_stats().await;
assert_eq!(stats.total_allocations, 0);
assert_eq!(stats.zero_copy_operations, 0);
}
#[tokio::test]
async fn test_prefetch_stats() {
let zc: _ = EnhancedZeroCopy::default();
let stats: _ = zc.get_prefetch_stats().await;
assert_eq!(stats.total_prefetches, 0);
assert_eq!(stats.successful_prefetches, 0);
assert_eq!(stats.success_rate(), 0.0);
}
#[test]
fn test_access_pattern() {
let sequential: _ = AccessPattern::Sequential;
let random: _ = AccessPattern::Random;
let _sequential_copy: _ = sequential;
let _random_copy: _ = random;
}
}