use crate::lock_free_temp::{AtomicStats, LockFreeBufferPool, LockFreeCounter};
use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex};
use std::fs::File;
use tokio::io::{AsyncSeekExt, AsyncWriteExt};
use std::time::Instant;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::num::NonZeroUsize;
use std::marker::PhantomData;
use tempfile::TempDir;
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct ZeroCopyBuffer {
data: Arc<[u8]>,
}
#[allow(dead_code)]
impl ZeroCopyBuffer {
pub fn new(data: Vec<u8>) -> Self {
Self {
data: Arc::from(data.into_boxed_slice()),
}
}
pub fn from_slice(data: &[u8]) -> Self {
Self {
data: Arc::from(data.to_vec().into_boxed_slice()),
}
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn as_slice(&self) -> &[u8] {
&self.data
}
pub fn to_vec(&self) -> Vec<u8> {
self.data.to_vec()
}
pub fn duplicate(&self) -> Self {
Self {
data: Arc::clone(&self.data),
}
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyChannel<T> {
sender: crossbeam::channel::Sender<T>,
receiver: crossbeam::channel::Receiver<T>,
_phantom: PhantomData<T>,
}
#[allow(dead_code)]
impl<T> ZeroCopyChannel<T> {
pub fn new(capacity: usize) -> Self {
let (sender, receiver) = crossbeam::channel::bounded(capacity);
Self {
sender,
receiver,
_phantom: PhantomData,
}
}
pub fn send(&self, data: T) -> Result<(), crossbeam::channel::SendError<T>> {
self.sender.send(data)
}
pub fn recv(&self) -> Result<T, crossbeam::channel::RecvError> {
self.receiver.recv()
}
pub fn try_send(&self, data: T) -> Result<(), crossbeam::channel::TrySendError<T>> {
self.sender.try_send(data)
}
pub fn try_recv(&self) -> Result<T, crossbeam::channel::TryRecvError> {
self.receiver.try_recv()
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyFileReader {
file: File,
}
#[allow(dead_code)]
impl ZeroCopyFileReader {
pub async fn new(path: &str) -> Result<Self, std::io::Error> {
let file: _ = tokio::fs::File::open(path).await?;
Ok(Self { file })
}
pub async fn read_to_buffer(&mut self) -> Result<ZeroCopyBuffer, std::io::Error> {
let metadata: _ = self.file.metadata().await?;
let size: _ = metadata.len() as usize;
let mut buffer = vec![0u8; size];
self.file.read_exact(&mut buffer).await?;
Ok(ZeroCopyBuffer::new(buffer))
}
pub async fn read_partial(&mut self, offset: u64, length: usize) -> Result<ZeroCopyBuffer, std::io::Error> {
self.file.seek(std::io::SeekFrom::Start(offset)).await?;
let mut buffer = vec![0u8; length];
self.file.read_exact(&mut buffer).await?;
Ok(ZeroCopyBuffer::new(buffer))
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyFileWriter {
file: File,
}
#[allow(dead_code)]
impl ZeroCopyFileWriter {
pub async fn new(path: &str) -> Result<Self, std::io::Error> {
let file: _ = tokio::fs::File::create(path).await?;
Ok(Self { file })
}
pub async fn write_from_buffer(&mut self, buffer: &ZeroCopyBuffer) -> Result<usize, std::io::Error> {
let bytes_written: _ = self.file.write(buffer.as_slice()).await?;
self.file.flush().await?;
Ok(bytes_written)
}
pub async fn append_from_buffer(&mut self, buffer: &ZeroCopyBuffer) -> Result<usize, std::io::Error> {
self.file.seek(std::io::SeekFrom::End(0)).await?;
let bytes_written: _ = self.file.write(buffer.as_slice()).await?;
self.file.flush().await?;
Ok(bytes_written)
}
}
#[cfg(unix)]
#[cfg(unix)]
#[allow(dead_code)]
pub struct MemoryMappedFile {
mapping: Arc<memmap2::Mmap>,
file: File,
}
#[cfg(unix)]
#[allow(dead_code)]
impl MemoryMappedFile {
pub async fn open(path: &str) -> Result<Self, std::io::Error> {
let file: _ = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(path)
.await?;
let mapping: _ = unsafe { memmap2::MmapOptions::new().map(&file)? };
Ok(Self {
mapping: Arc::new(Mutex::new(mapping)),
file,
})
}
pub fn as_slice(&self) -> &[u8] {
&self.mapping
}
pub fn sync(&self) -> Result<(), std::io::Error> {
let _: _ = Arc::as_ptr(&self.mapping);
Ok(())
}
pub fn read_chunk(&self, offset: usize, size: usize) -> Result<&[u8], std::io::Error> {
if offset + size > self.mapping.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Offset + size exceeds file size"
));
}
Ok(&self.mapping[offset..offset + size])
}
pub fn len(&self) -> usize {
self.mapping.len()
}
pub fn is_empty(&self) -> bool {
self.mapping.is_empty()
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyManager {
buffer_pool: LockFreeBufferPool,
channel_stats: Arc<AtomicStats>,
}
#[allow(dead_code)]
impl ZeroCopyManager {
pub fn new() -> Self {
Self {
buffer_pool: LockFreeBufferPool::new(),
channel_stats: Arc::new(Mutex::new(AtomicStats::new())),
}
}
pub fn create_channel<T>(&self, capacity: usize) -> ZeroCopyChannel<T> {
self.channel_stats.record_operation("create_channel");
ZeroCopyChannel::new(capacity)
}
pub fn create_buffer(&self, data: Vec<u8>) -> ZeroCopyBuffer {
self.buffer_pool.allocate(data.len());
ZeroCopyBuffer::new(data)
}
pub fn clone_buffer(&self, buffer: &ZeroCopyBuffer) -> ZeroCopyBuffer {
self.channel_stats.record_operation("clone_buffer");
buffer.duplicate()
}
pub fn destroy_buffer(&self, _buffer: &ZeroCopyBuffer) {
self.buffer_pool.deallocate(Vec::new());
}
pub fn get_stats(&self) -> String {
format!(
"Buffer Pool: Active={}, Total Allocations={}, Available={}\nChannel Stats: {}",
self.buffer_pool.active_count(),
self.buffer_pool.total_allocations(),
self.buffer_pool.available_count(),
self.channel_stats.get_report()
)
}
pub fn reset_stats(&self) {
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyMessage<T> {
data: T,
metadata: MessageMetadata,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct MessageMetadata {
pub timestamp: std::time::Instant,
pub size: usize,
pub priority: u8,
}
#[allow(dead_code)]
impl<T> ZeroCopyMessage<T> {
pub fn new(data: T) -> Self {
Self {
data,
metadata: MessageMetadata {
timestamp: std::time::Instant::now(),
size: std::mem::size_of::<T>(),
priority: 0,
},
}
}
pub fn new_with_priority(data: T, priority: u8) -> Self {
Self {
data,
metadata: MessageMetadata {
timestamp: std::time::Instant::now(),
size: std::mem::size_of::<T>(),
priority,
},
}
}
pub fn get_data(&self) -> &T {
&self.data
}
pub fn get_metadata(&self) -> &MessageMetadata {
&self.metadata
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyRingBuffer<T> {
buffer: Vec<Option<T>>,
write_index: LockFreeCounter,
read_index: LockFreeCounter,
capacity: usize,
}
#[allow(dead_code)]
impl<T> ZeroCopyRingBuffer<T> {
pub fn new(capacity: usize) -> Self {
let mut buffer = Vec::with_capacity(capacity);
for _ in 0..capacity {
buffer.push(None);
}
Self {
buffer,
write_index: LockFreeCounter::new(0),
read_index: LockFreeCounter::new(0),
capacity,
}
}
pub fn try_write(&mut self, item: T) -> bool {
let write_pos: _ = self.write_index.load();
let read_pos: _ = self.read_index.load();
if (write_pos + 1) % self.capacity == read_pos % self.capacity {
return false;
}
let index: _ = write_pos % self.capacity;
self.buffer[index] = Some(item);
self.write_index.increment();
true
}
pub fn try_read(&mut self) -> Option<T> {
let write_pos: _ = self.write_index.load();
let read_pos: _ = self.read_index.load();
if write_pos == read_pos {
return None;
}
let index: _ = read_pos % self.capacity;
let item: _ = self.buffer[index].take();
if item.is_some() {
self.read_index.increment();
}
item
}
pub fn utilization(&self) -> f64 {
let write_pos: _ = self.write_index.load();
let read_pos: _ = self.read_index.load();
let used: _ = (write_pos - read_pos).max(0) as f64;
used / self.capacity as f64
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_zero_copy_buffer() {
let data: _ = vec![1, 2, 3, 4, 5];
let buffer: _ = ZeroCopyBuffer::new(data.clone());
assert_eq!(buffer.len(), 5);
assert_eq!(buffer.as_slice(), &data);
let cloned: _ = buffer.duplicate();
assert_eq!(cloned.as_slice(), &data);
assert!(Arc::ptr_eq(&buffer.data, &cloned.data));
}
#[test]
fn test_zero_copy_channel() {
let channel: _ = ZeroCopyChannel::new(10);
channel.send(42).unwrap();
let received: _ = channel.recv().unwrap();
assert_eq!(received, 42);
}
#[tokio::test]
async fn test_zero_copy_file_reader() {
let temp_dir: _ = TempDir::new().unwrap();
let file_path: _ = temp_dir.path().join("test.txt");
fs::write(&file_path, "Hello, World!").unwrap();
let mut reader = ZeroCopyFileReader::new(file_path.to_str().unwrap()).await.unwrap();
let buffer: _ = reader.read_to_buffer().await.unwrap();
assert_eq!(buffer.len(), 13);
assert_eq!(buffer.as_slice(), b"Hello, World!");
}
#[tokio::test]
async fn test_zero_copy_file_writer() {
let temp_dir: _ = TempDir::new().unwrap();
let file_path: _ = temp_dir.path().join("output.txt");
let buffer: _ = ZeroCopyBuffer::from_slice(b"Test Data");
let mut writer = ZeroCopyFileWriter::new(file_path.to_str().unwrap()).await.unwrap();
let bytes_written: _ = writer.write_from_buffer(&buffer).await.unwrap();
assert_eq!(bytes_written, 9);
let content: _ = fs::read_to_string(file_path).unwrap();
assert_eq!(content, "Test Data");
}
#[test]
fn test_zero_copy_message() {
let message: _ = ZeroCopyMessage::new_with_priority("test".to_string(), 5);
assert_eq!(message.get_metadata().priority, 5);
assert_eq!(message.get_data(), &"test".to_string());
}
#[test]
fn test_zero_copy_ring_buffer() {
let mut buffer = ZeroCopyRingBuffer::new(5);
assert!(buffer.try_write(1));
assert!(buffer.try_write(2));
assert!(buffer.try_write(3));
assert_eq!(buffer.try_read(), Some(1));
assert_eq!(buffer.try_read(), Some(2));
assert!(buffer.utilization() > 0.0);
}
#[test]
fn test_zero_copy_manager() {
let manager: _ = ZeroCopyManager::new();
let buffer: _ = manager.create_buffer(vec![1, 2, 3]);
assert_eq!(buffer.len(), 3);
let channel: _ = manager.create_channel::<i32>(10);
assert!(channel.send(42).is_ok());
let stats: _ = manager.get_stats();
assert!(stats.contains("Buffer Pool"));
assert!(stats.contains("Channel Stats"));
}
#[test]
fn test_atomic_operations_performance() {
let counter: _ = Arc::new(Mutex::new(LockFreeCounter::new(0)));
let iterations: _ = 100000;
let thread_count: _ = 4;
let start: _ = std::time::Instant::now();
let handles: Vec<_> = (0..thread_count)
.map(|_| {
let counter: _ = counter.clone();
std::thread::spawn(move || {
for _ in 0..iterations {
counter.increment();
}
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
let elapsed: _ = start.elapsed();
let total_ops: _ = counter.load();
println!("{} 个线程执行 {} 次原子操作,总计 {} 次,耗时: {:?}",
thread_count, iterations, total_ops, elapsed);
assert_eq!(total_ops, thread_count * iterations);
assert!(elapsed.as_millis() < 1000); }
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyFileCache {
cache: Arc<Mutex<lru::LruCache<String, Arc<memmap2::Mmap>>>>,
max_entries: usize,
stats: Arc<AtomicStats>,
}
#[allow(dead_code)]
impl ZeroCopyFileCache {
pub fn new(max_entries: usize) -> Self {
Self {
cache: Arc::new(Mutex::new(lru::LruCache::new(
std::num::NonZeroUsize::new(max_entries)
).unwrap())),
max_entries,
stats: Arc::new(Mutex::new(AtomicStats::new())),
}
}
pub async fn get_or_load(&self, path: &str) -> Result<Arc<memmap2::Mmap>, std::io::Error> {
let path_string: _ = path.to_string();
{
let mut cache = self.cache.lock().unwrap();
if let Some(mapping) = cache.get(&path_string) {
self.stats.record_operation("cache_hit");
return Ok(Arc::clone(mapping));
}
}
let file: _ = tokio::fs::File::open(path).await?;
let mapping: _ = unsafe { memmap2::MmapOptions::new().map(&file)? };
let mapping: _ = Arc::new(Mutex::new(mapping));
{
let mut cache = self.cache.lock().unwrap();
cache.put(path_string, Arc::clone(mapping));
}
self.stats.record_operation("cache_miss");
Ok(mapping)
}
pub async fn preload(&self, path: &str) -> Result<(), std::io::Error> {
let _: _ = self.get_or_load(path).await?;
Ok(())
}
pub fn remove(&self, path: &str) -> Option<Arc<memmap2::Mmap>> {
let mut cache = self.cache.lock().unwrap();
cache.pop(path)
}
pub fn clear(&self) {
let mut cache = self.cache.lock().unwrap();
cache.clear();
}
pub fn get_stats(&self) -> String {
let cache: _ = self.cache.lock().unwrap();
format!(
"Zero-copy file cache: {} entries (max: {}), operations: {}",
cache.len(),
self.max_entries,
self.stats.get_report()
)
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct ZeroCopyIoMonitor {
zero_copy_bytes: Arc<AtomicUsize>,
copied_bytes: Arc<AtomicUsize>,
file_ops: Arc<AtomicUsize>,
cache_hits: Arc<AtomicUsize>,
cache_misses: Arc<AtomicUsize>,
}
#[allow(dead_code)]
impl ZeroCopyIoMonitor {
pub fn new() -> Self {
Self {
zero_copy_bytes: Arc::new(Mutex::new(AtomicUsize::new(0))),
copied_bytes: Arc::new(Mutex::new(AtomicUsize::new(0))),
file_ops: Arc::new(Mutex::new(AtomicUsize::new(0))),
cache_hits: Arc::new(Mutex::new(AtomicUsize::new(0))),
cache_misses: Arc::new(Mutex::new(AtomicUsize::new(0))),
}
}
pub fn record_zero_copy(&self, bytes: usize) {
self.zero_copy_bytes.fetch_add(bytes, Ordering::Relaxed);
self.file_ops.fetch_add(1, Ordering::Relaxed);
}
pub fn record_copy(&self, bytes: usize) {
self.copied_bytes.fetch_add(bytes, Ordering::Relaxed);
self.file_ops.fetch_add(1, Ordering::Relaxed);
}
pub fn record_cache_hit(&self) {
self.cache_hits.fetch_add(1, Ordering::Relaxed);
}
pub fn record_cache_miss(&self) {
self.cache_misses.fetch_add(1, Ordering::Relaxed);
}
pub fn get_zero_copy_ratio(&self) -> f64 {
let zero_copy: _ = self.zero_copy_bytes.load(Ordering::Relaxed) as f64;
let total: _ = zero_copy + self.copied_bytes.load(Ordering::Relaxed) as f64;
if total > 0.0 { zero_copy / total } else { 0.0 }
}
pub fn get_cache_hit_rate(&self) -> f64 {
let hits: _ = self.cache_hits.load(Ordering::Relaxed) as f64;
let total: _ = hits + self.cache_misses.load(Ordering::Relaxed) as f64;
if total > 0.0 { hits / total } else { 0.0 }
}
pub fn get_performance_report(&self) -> String {
let zero_copy: _ = self.zero_copy_bytes.load(Ordering::Relaxed);
let copied: _ = self.copied_bytes.load(Ordering::Relaxed);
let file_ops: _ = self.file_ops.load(Ordering::Relaxed);
let cache_hit_rate: _ = self.get_cache_hit_rate();
let zero_copy_ratio: _ = self.get_zero_copy_ratio();
format!(
"Zero-copy I/O Performance Report:\n\
- Total file operations: {}\n\
- Zero-copy bytes: {} ({:.2}%)\n\
- Copied bytes: {} ({:.2}%)\n\
- Cache hit rate: {:.2}%\n\
- Zero-copy ratio: {:.2}%",
file_ops,
zero_copy,
zero_copy_ratio * 100.0,
copied,
(1.0 - zero_copy_ratio) * 100.0,
cache_hit_rate * 100.0,
zero_copy_ratio * 100.0
)
}
}