style: run rustfmt
This commit is contained in:
+133
-126
@@ -1,5 +1,5 @@
|
||||
//! 🚀 零拷贝内存映射IO - 完全消除数据拷贝开销
|
||||
//!
|
||||
//!
|
||||
//! 实现极致的零拷贝策略,包括:
|
||||
//! - 内存映射文件IO
|
||||
//! - 共享内存环形缓冲区
|
||||
@@ -10,11 +10,11 @@
|
||||
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
// use std::mem::{size_of, MaybeUninit};
|
||||
use anyhow::{Context, Result};
|
||||
use crossbeam_utils::CachePadded;
|
||||
use memmap2::{MmapMut, MmapOptions};
|
||||
use std::ptr::NonNull;
|
||||
use std::slice;
|
||||
use memmap2::{MmapMut, MmapOptions};
|
||||
use anyhow::{Result, Context};
|
||||
use crossbeam_utils::CachePadded;
|
||||
|
||||
/// 🚀 零拷贝内存管理器
|
||||
pub struct ZeroCopyMemoryManager {
|
||||
@@ -50,17 +50,17 @@ impl SharedMemoryPool {
|
||||
// 确保块大小是64字节对齐(缓存行对齐)
|
||||
let aligned_block_size = (block_size + 63) & !63;
|
||||
let total_blocks = total_size / aligned_block_size;
|
||||
|
||||
|
||||
// 创建内存映射文件
|
||||
let memory_region = MmapOptions::new()
|
||||
.len(total_blocks * aligned_block_size)
|
||||
.map_anon()
|
||||
.context("Failed to create memory mapped region")?;
|
||||
|
||||
|
||||
// 初始化空闲块位图 (每个u64可以管理64个块)
|
||||
let bitmap_size = (total_blocks + 63) / 64;
|
||||
let mut free_blocks = Vec::with_capacity(bitmap_size);
|
||||
|
||||
|
||||
// 将所有块标记为空闲(全1)
|
||||
for i in 0..bitmap_size {
|
||||
let bits = if i == bitmap_size - 1 && total_blocks % 64 != 0 {
|
||||
@@ -72,10 +72,10 @@ impl SharedMemoryPool {
|
||||
};
|
||||
free_blocks.push(AtomicU64::new(bits));
|
||||
}
|
||||
|
||||
|
||||
tracing::info!(target: "sol_trade_sdk","🚀 Created shared memory pool {} with {} blocks of {} bytes each",
|
||||
pool_id, total_blocks, aligned_block_size);
|
||||
|
||||
|
||||
Ok(Self {
|
||||
memory_region,
|
||||
free_blocks,
|
||||
@@ -85,31 +85,31 @@ impl SharedMemoryPool {
|
||||
pool_id,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 零拷贝分配内存块
|
||||
#[inline(always)]
|
||||
pub fn allocate_block(&self) -> Option<ZeroCopyBlock> {
|
||||
// 快速路径:尝试从预期位置分配
|
||||
let start_index = self.allocator_head.load(Ordering::Relaxed) / 64;
|
||||
|
||||
|
||||
// 遍历所有位图寻找空闲块
|
||||
for attempt in 0..self.free_blocks.len() {
|
||||
let bitmap_index = (start_index + attempt) % self.free_blocks.len();
|
||||
let bitmap = &self.free_blocks[bitmap_index];
|
||||
|
||||
|
||||
let mut current = bitmap.load(Ordering::Acquire);
|
||||
|
||||
|
||||
while current != 0 {
|
||||
// 找到最低位的1(最小的空闲块)
|
||||
let bit_pos = current.trailing_zeros() as usize;
|
||||
let mask = 1u64 << bit_pos;
|
||||
|
||||
|
||||
// 尝试原子地清除这一位(标记为已分配)
|
||||
match bitmap.compare_exchange_weak(
|
||||
current,
|
||||
current,
|
||||
current & !mask,
|
||||
Ordering::AcqRel,
|
||||
Ordering::Relaxed
|
||||
Ordering::Relaxed,
|
||||
) {
|
||||
Ok(_) => {
|
||||
// 成功分配
|
||||
@@ -119,20 +119,17 @@ impl SharedMemoryPool {
|
||||
bitmap.fetch_or(mask, Ordering::Relaxed);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
let offset = block_index * self.block_size;
|
||||
let ptr = unsafe {
|
||||
NonNull::new_unchecked(
|
||||
self.memory_region.as_ptr().add(offset) as *mut u8
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
// 更新分配器头指针
|
||||
self.allocator_head.store(
|
||||
(block_index + 1) * 64,
|
||||
Ordering::Relaxed
|
||||
);
|
||||
|
||||
self.allocator_head.store((block_index + 1) * 64, Ordering::Relaxed);
|
||||
|
||||
return Some(ZeroCopyBlock {
|
||||
ptr,
|
||||
size: self.block_size,
|
||||
@@ -147,10 +144,10 @@ impl SharedMemoryPool {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
None // 没有可用块
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 零拷贝释放内存块
|
||||
#[inline(always)]
|
||||
pub fn deallocate_block(&self, block: ZeroCopyBlock) {
|
||||
@@ -158,20 +155,21 @@ impl SharedMemoryPool {
|
||||
tracing::error!(target: "sol_trade_sdk", "Attempting to deallocate block from wrong pool");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let bitmap_index = block.block_index / 64;
|
||||
let bit_pos = block.block_index % 64;
|
||||
let mask = 1u64 << bit_pos;
|
||||
|
||||
|
||||
if bitmap_index < self.free_blocks.len() {
|
||||
// 原子地设置位为1(标记为空闲)
|
||||
self.free_blocks[bitmap_index].fetch_or(mask, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 获取可用块数量
|
||||
pub fn available_blocks(&self) -> usize {
|
||||
self.free_blocks.iter()
|
||||
self.free_blocks
|
||||
.iter()
|
||||
.map(|bitmap| bitmap.load(Ordering::Relaxed).count_ones() as usize)
|
||||
.sum()
|
||||
}
|
||||
@@ -195,49 +193,49 @@ impl ZeroCopyBlock {
|
||||
pub fn as_ptr(&self) -> *mut u8 {
|
||||
self.ptr.as_ptr()
|
||||
}
|
||||
|
||||
|
||||
/// 获取只读切片
|
||||
#[inline(always)]
|
||||
pub unsafe fn as_slice(&self) -> &[u8] {
|
||||
slice::from_raw_parts(self.ptr.as_ptr(), self.size)
|
||||
}
|
||||
|
||||
|
||||
/// 获取可变切片
|
||||
#[inline(always)]
|
||||
pub unsafe fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||
slice::from_raw_parts_mut(self.ptr.as_ptr(), self.size)
|
||||
}
|
||||
|
||||
|
||||
/// 获取块大小
|
||||
#[inline(always)]
|
||||
pub fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
|
||||
|
||||
/// 零拷贝写入数据
|
||||
#[inline(always)]
|
||||
pub unsafe fn write_bytes(&mut self, data: &[u8]) -> Result<()> {
|
||||
if data.len() > self.size {
|
||||
return Err(anyhow::anyhow!("Data too large for block"));
|
||||
}
|
||||
|
||||
|
||||
// 使用硬件优化的内存拷贝
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
self.ptr.as_ptr(),
|
||||
data.as_ptr(),
|
||||
data.len()
|
||||
data.len(),
|
||||
);
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
/// 零拷贝读取数据
|
||||
#[inline(always)]
|
||||
pub unsafe fn read_bytes(&self, len: usize) -> Result<&[u8]> {
|
||||
if len > self.size {
|
||||
return Err(anyhow::anyhow!("Read length exceeds block size"));
|
||||
}
|
||||
|
||||
|
||||
Ok(slice::from_raw_parts(self.ptr.as_ptr(), len))
|
||||
}
|
||||
}
|
||||
@@ -266,9 +264,9 @@ impl MemoryMappedBuffer {
|
||||
.len(size)
|
||||
.map_anon()
|
||||
.context("Failed to create memory mapped buffer")?;
|
||||
|
||||
|
||||
tracing::info!(target: "sol_trade_sdk","🚀 Created memory mapped buffer {} with size {} bytes", buffer_id, size);
|
||||
|
||||
|
||||
Ok(Self {
|
||||
mmap,
|
||||
read_pos: CachePadded::new(AtomicUsize::new(0)),
|
||||
@@ -277,128 +275,136 @@ impl MemoryMappedBuffer {
|
||||
_buffer_id: buffer_id,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 零拷贝写入数据
|
||||
#[inline(always)]
|
||||
pub fn write_data(&self, data: &[u8]) -> Result<usize> {
|
||||
let data_len = data.len();
|
||||
let current_write = self.write_pos.load(Ordering::Relaxed);
|
||||
let current_read = self.read_pos.load(Ordering::Acquire);
|
||||
|
||||
|
||||
// 计算可用空间
|
||||
let available_space = if current_write >= current_read {
|
||||
self.size - (current_write - current_read) - 1
|
||||
} else {
|
||||
current_read - current_write - 1
|
||||
};
|
||||
|
||||
|
||||
if data_len > available_space {
|
||||
return Err(anyhow::anyhow!("Insufficient buffer space"));
|
||||
}
|
||||
|
||||
|
||||
// 零拷贝写入
|
||||
unsafe {
|
||||
let write_ptr = self.mmap.as_ptr().add(current_write) as *mut u8;
|
||||
|
||||
|
||||
if current_write + data_len <= self.size {
|
||||
// 数据不跨越缓冲区边界
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
write_ptr, data.as_ptr(), data_len
|
||||
write_ptr,
|
||||
data.as_ptr(),
|
||||
data_len,
|
||||
);
|
||||
} else {
|
||||
// 数据跨越缓冲区边界,分两段写入
|
||||
let first_part = self.size - current_write;
|
||||
let second_part = data_len - first_part;
|
||||
|
||||
|
||||
// 写入第一部分
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
write_ptr, data.as_ptr(), first_part
|
||||
write_ptr,
|
||||
data.as_ptr(),
|
||||
first_part,
|
||||
);
|
||||
|
||||
|
||||
// 写入第二部分(从缓冲区开头)
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
self.mmap.as_ptr() as *mut u8,
|
||||
data.as_ptr().add(first_part),
|
||||
second_part
|
||||
self.mmap.as_ptr() as *mut u8,
|
||||
data.as_ptr().add(first_part),
|
||||
second_part,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 更新写指针
|
||||
let new_write_pos = (current_write + data_len) % self.size;
|
||||
self.write_pos.store(new_write_pos, Ordering::Release);
|
||||
|
||||
|
||||
Ok(data_len)
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 零拷贝读取数据
|
||||
#[inline(always)]
|
||||
pub fn read_data(&self, buffer: &mut [u8]) -> Result<usize> {
|
||||
let buffer_len = buffer.len();
|
||||
let current_read = self.read_pos.load(Ordering::Relaxed);
|
||||
let current_write = self.write_pos.load(Ordering::Acquire);
|
||||
|
||||
|
||||
// 计算可读数据量
|
||||
let available_data = if current_write >= current_read {
|
||||
current_write - current_read
|
||||
} else {
|
||||
self.size - (current_read - current_write)
|
||||
};
|
||||
|
||||
|
||||
if available_data == 0 {
|
||||
return Ok(0); // 无数据可读
|
||||
}
|
||||
|
||||
|
||||
let read_len = buffer_len.min(available_data);
|
||||
|
||||
|
||||
// 零拷贝读取
|
||||
unsafe {
|
||||
let read_ptr = self.mmap.as_ptr().add(current_read);
|
||||
|
||||
|
||||
if current_read + read_len <= self.size {
|
||||
// 数据不跨越缓冲区边界
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
buffer.as_mut_ptr(), read_ptr, read_len
|
||||
buffer.as_mut_ptr(),
|
||||
read_ptr,
|
||||
read_len,
|
||||
);
|
||||
} else {
|
||||
// 数据跨越缓冲区边界,分两段读取
|
||||
let first_part = self.size - current_read;
|
||||
let second_part = read_len - first_part;
|
||||
|
||||
|
||||
// 读取第一部分
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
buffer.as_mut_ptr(), read_ptr, first_part
|
||||
buffer.as_mut_ptr(),
|
||||
read_ptr,
|
||||
first_part,
|
||||
);
|
||||
|
||||
|
||||
// 读取第二部分(从缓冲区开头)
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
buffer.as_mut_ptr().add(first_part),
|
||||
self.mmap.as_ptr(),
|
||||
second_part
|
||||
self.mmap.as_ptr(),
|
||||
second_part,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 更新读指针
|
||||
let new_read_pos = (current_read + read_len) % self.size;
|
||||
self.read_pos.store(new_read_pos, Ordering::Release);
|
||||
|
||||
|
||||
Ok(read_len)
|
||||
}
|
||||
|
||||
|
||||
/// 获取可读数据量
|
||||
#[inline(always)]
|
||||
pub fn available_data(&self) -> usize {
|
||||
let current_read = self.read_pos.load(Ordering::Relaxed);
|
||||
let current_write = self.write_pos.load(Ordering::Relaxed);
|
||||
|
||||
|
||||
if current_write >= current_read {
|
||||
current_write - current_read
|
||||
} else {
|
||||
self.size - (current_read - current_write)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 获取可用空间
|
||||
#[inline(always)]
|
||||
pub fn available_space(&self) -> usize {
|
||||
@@ -420,38 +426,39 @@ impl DirectMemoryAccessManager {
|
||||
/// 创建DMA管理器
|
||||
pub fn new(num_channels: usize) -> Result<Self> {
|
||||
let mut dma_channels = Vec::with_capacity(num_channels);
|
||||
|
||||
|
||||
for i in 0..num_channels {
|
||||
dma_channels.push(Arc::new(DMAChannel::new(i)?));
|
||||
}
|
||||
|
||||
|
||||
tracing::info!(target: "sol_trade_sdk","🚀 Created DMA manager with {} channels", num_channels);
|
||||
|
||||
|
||||
Ok(Self {
|
||||
dma_channels,
|
||||
channel_allocator: AtomicUsize::new(0),
|
||||
dma_stats: Arc::new(DMAStats::new()),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 执行零拷贝DMA传输
|
||||
#[inline(always)]
|
||||
pub async fn dma_transfer(&self, src: &[u8], dst: &mut [u8]) -> Result<usize> {
|
||||
if src.len() != dst.len() {
|
||||
return Err(anyhow::anyhow!("Source and destination sizes don't match"));
|
||||
}
|
||||
|
||||
|
||||
// 选择DMA通道(轮询分配)
|
||||
let channel_index = self.channel_allocator.fetch_add(1, Ordering::Relaxed) % self.dma_channels.len();
|
||||
let channel_index =
|
||||
self.channel_allocator.fetch_add(1, Ordering::Relaxed) % self.dma_channels.len();
|
||||
let channel = &self.dma_channels[channel_index];
|
||||
|
||||
|
||||
// 执行DMA传输
|
||||
let transferred = channel.transfer(src, dst).await?;
|
||||
|
||||
|
||||
// 更新统计
|
||||
self.dma_stats.bytes_transferred.fetch_add(transferred as u64, Ordering::Relaxed);
|
||||
self.dma_stats.transfers_completed.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
|
||||
Ok(transferred)
|
||||
}
|
||||
}
|
||||
@@ -475,21 +482,21 @@ impl DMAChannel {
|
||||
_status: AtomicU64::new(0),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 执行零拷贝传输
|
||||
#[inline(always)]
|
||||
pub async fn transfer(&self, src: &[u8], dst: &mut [u8]) -> Result<usize> {
|
||||
let transfer_size = src.len();
|
||||
|
||||
|
||||
// 使用硬件优化的SIMD内存拷贝
|
||||
unsafe {
|
||||
super::hardware_optimizations::SIMDMemoryOps::memcpy_simd_optimized(
|
||||
dst.as_mut_ptr(),
|
||||
src.as_ptr(),
|
||||
transfer_size
|
||||
transfer_size,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Ok(transfer_size)
|
||||
}
|
||||
}
|
||||
@@ -541,14 +548,14 @@ impl ZeroCopyStats {
|
||||
mmap_buffer_usage: AtomicU64::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 打印统计信息
|
||||
pub fn print_stats(&self) {
|
||||
let allocated = self.blocks_allocated.load(Ordering::Relaxed);
|
||||
let freed = self.blocks_freed.load(Ordering::Relaxed);
|
||||
let bytes = self.bytes_transferred.load(Ordering::Relaxed);
|
||||
let mmap_usage = self.mmap_buffer_usage.load(Ordering::Relaxed);
|
||||
|
||||
|
||||
tracing::info!(target: "sol_trade_sdk","🚀 Zero-Copy Stats:");
|
||||
tracing::info!(target: "sol_trade_sdk"," 📦 Blocks: Allocated={}, Freed={}, Active={}",
|
||||
allocated, freed, allocated.saturating_sub(freed));
|
||||
@@ -564,36 +571,36 @@ impl ZeroCopyMemoryManager {
|
||||
pub fn new() -> Result<Self> {
|
||||
let mut shared_pools = Vec::new();
|
||||
let mut mmap_buffers = Vec::new();
|
||||
|
||||
|
||||
// 创建不同大小的内存池
|
||||
// 小块池: 64KB blocks, 1GB total
|
||||
shared_pools.push(Arc::new(SharedMemoryPool::new(0, 1024 * 1024 * 1024, 64 * 1024)?));
|
||||
// 中块池: 1MB blocks, 4GB total
|
||||
// 中块池: 1MB blocks, 4GB total
|
||||
shared_pools.push(Arc::new(SharedMemoryPool::new(1, 4 * 1024 * 1024 * 1024, 1024 * 1024)?));
|
||||
// 大块池: 16MB blocks, 8GB total
|
||||
shared_pools.push(Arc::new(SharedMemoryPool::new(2, 8 * 1024 * 1024 * 1024, 16 * 1024 * 1024)?));
|
||||
|
||||
shared_pools.push(Arc::new(SharedMemoryPool::new(
|
||||
2,
|
||||
8 * 1024 * 1024 * 1024,
|
||||
16 * 1024 * 1024,
|
||||
)?));
|
||||
|
||||
// 创建内存映射缓冲区
|
||||
for i in 0..8 {
|
||||
mmap_buffers.push(Arc::new(MemoryMappedBuffer::new(i, 256 * 1024 * 1024)?)); // 256MB each
|
||||
mmap_buffers.push(Arc::new(MemoryMappedBuffer::new(i, 256 * 1024 * 1024)?));
|
||||
// 256MB each
|
||||
}
|
||||
|
||||
|
||||
let dma_manager = Arc::new(DirectMemoryAccessManager::new(16)?); // 16 DMA channels
|
||||
let stats = Arc::new(ZeroCopyStats::new());
|
||||
|
||||
|
||||
tracing::info!(target: "sol_trade_sdk","🚀 Zero-Copy Memory Manager initialized");
|
||||
tracing::info!(target: "sol_trade_sdk"," 📦 Memory Pools: {}", shared_pools.len());
|
||||
tracing::info!(target: "sol_trade_sdk"," 💾 Mapped Buffers: {}", mmap_buffers.len());
|
||||
tracing::info!(target: "sol_trade_sdk"," 🔄 DMA Channels: 16");
|
||||
|
||||
Ok(Self {
|
||||
shared_pools,
|
||||
mmap_buffers,
|
||||
dma_manager,
|
||||
stats,
|
||||
})
|
||||
|
||||
Ok(Self { shared_pools, mmap_buffers, dma_manager, stats })
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 分配零拷贝内存块
|
||||
#[inline(always)]
|
||||
pub fn allocate(&self, size: usize) -> Option<ZeroCopyBlock> {
|
||||
@@ -605,7 +612,7 @@ impl ZeroCopyMemoryManager {
|
||||
} else {
|
||||
&self.shared_pools[2] // 大块池
|
||||
};
|
||||
|
||||
|
||||
if let Some(block) = pool.allocate_block() {
|
||||
self.stats.blocks_allocated.fetch_add(1, Ordering::Relaxed);
|
||||
Some(block)
|
||||
@@ -613,7 +620,7 @@ impl ZeroCopyMemoryManager {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 🚀 释放零拷贝内存块
|
||||
#[inline(always)]
|
||||
pub fn deallocate(&self, block: ZeroCopyBlock) {
|
||||
@@ -623,19 +630,19 @@ impl ZeroCopyMemoryManager {
|
||||
self.stats.blocks_freed.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 获取内存映射缓冲区
|
||||
#[inline(always)]
|
||||
pub fn get_mmap_buffer(&self, buffer_id: usize) -> Option<Arc<MemoryMappedBuffer>> {
|
||||
self.mmap_buffers.get(buffer_id).cloned()
|
||||
}
|
||||
|
||||
|
||||
/// 获取DMA管理器
|
||||
#[inline(always)]
|
||||
pub fn get_dma_manager(&self) -> Arc<DirectMemoryAccessManager> {
|
||||
self.dma_manager.clone()
|
||||
}
|
||||
|
||||
|
||||
/// 获取统计信息
|
||||
pub fn get_stats(&self) -> Arc<ZeroCopyStats> {
|
||||
self.stats.clone()
|
||||
@@ -645,73 +652,73 @@ impl ZeroCopyMemoryManager {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_shared_memory_pool() -> Result<()> {
|
||||
let pool = SharedMemoryPool::new(0, 1024 * 1024, 4096)?;
|
||||
|
||||
|
||||
// 测试分配
|
||||
let block1 = pool.allocate_block().expect("Should allocate block");
|
||||
assert_eq!(block1.size(), 4096);
|
||||
|
||||
|
||||
let block2 = pool.allocate_block().expect("Should allocate another block");
|
||||
assert_eq!(block2.size(), 4096);
|
||||
|
||||
|
||||
// 测试释放
|
||||
pool.deallocate_block(block1);
|
||||
pool.deallocate_block(block2);
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_memory_mapped_buffer() -> Result<()> {
|
||||
let buffer = MemoryMappedBuffer::new(0, 1024 * 1024)?;
|
||||
|
||||
|
||||
let test_data = b"Hello, Zero-Copy World!";
|
||||
|
||||
|
||||
// 测试写入
|
||||
let written = buffer.write_data(test_data)?;
|
||||
assert_eq!(written, test_data.len());
|
||||
|
||||
|
||||
// 测试读取
|
||||
let mut read_buffer = vec![0u8; test_data.len()];
|
||||
let read = buffer.read_data(&mut read_buffer)?;
|
||||
assert_eq!(read, test_data.len());
|
||||
assert_eq!(&read_buffer, test_data);
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dma_transfer() -> Result<()> {
|
||||
let dma_manager = DirectMemoryAccessManager::new(4)?;
|
||||
|
||||
|
||||
let src = vec![1u8, 2, 3, 4, 5, 6, 7, 8];
|
||||
let mut dst = vec![0u8; 8];
|
||||
|
||||
|
||||
let transferred = dma_manager.dma_transfer(&src, &mut dst).await?;
|
||||
assert_eq!(transferred, 8);
|
||||
assert_eq!(src, dst);
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_zero_copy_manager() -> Result<()> {
|
||||
let manager = ZeroCopyMemoryManager::new()?;
|
||||
|
||||
|
||||
// 测试小块分配
|
||||
let small_block = manager.allocate(1024).expect("Should allocate small block");
|
||||
assert_eq!(small_block.size(), 65536); // 小块池的块大小
|
||||
|
||||
|
||||
// 测试大块分配
|
||||
let large_block = manager.allocate(5 * 1024 * 1024).expect("Should allocate large block");
|
||||
assert_eq!(large_block.size(), 16 * 1024 * 1024); // 大块池的块大小
|
||||
|
||||
|
||||
manager.deallocate(small_block);
|
||||
manager.deallocate(large_block);
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user