use std::collections::{BTreeMap, HashMap};
use std::io::{Seek, SeekFrom, self};
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::{Arc, Mutex};
use std::sync::atomic::Ordering;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf};
use tokio::net::{TcpListener, TcpStream};
use tokio::sync::{Mutex as TokioMutex, Semaphore};
use std::time::{Duration, Instant};
use std::sync::atomic::AtomicU64;
use std::net::TcpListener as StdTcpListener;
pub use super::{
ZeroCopyConfig, ZeroCopyError, ZeroCopyMonitor, ZeroCopyMetrics,
ZeroCopyDirection,
};
#[derive(Debug, Clone)]
struct AsyncZeroCopyTask {
id: u64,
src_fd: RawFd,
dst_fd: RawFd,
offset: u64,
length: usize,
direction: ZeroCopyDirection,
status: TaskStatus,
start_time: Instant,
end_time: Option<Instant>,
}
#[derive(Debug, Clone, PartialEq)]
enum TaskStatus {
Pending,
Running,
Completed,
Failed(String),
}
#[derive(Debug, Clone, Default)]
pub struct AsyncZeroCopyStats {
pub total_tasks: u64,
pub success_tasks: u64,
pub failed_tasks: u64,
pub total_bytes: u64,
pub avg_latency_us: u64,
pub peak_speed: f64,
}
#[derive(Debug)]
pub struct AsyncZeroCopy {
config: ZeroCopyConfig,
monitor: Arc<ZeroCopyMonitor>,
stats: Arc<TokioMutex<AsyncZeroCopyStats>>,
active_tasks: Arc<TokioMutex<HashMap<u64, AsyncZeroCopyTask>>>,
next_task_id: Arc<std::sync::atomic::AtomicU64>,
semaphore: Arc<Semaphore>,
}
impl AsyncZeroCopy {
pub fn new(config: Option<ZeroCopyConfig>) -> io::Result<Self> {
let config: _ = config.unwrap_or_default();
let monitor: _ = Arc::new(Mutex::new(ZeroCopyMonitor::new()));
Ok(Self {
config,
monitor,
stats: Arc::new(Mutex::new(TokioMutex::new(AsyncZeroCopyStats::default()))),
active_tasks: Arc::new(Mutex::new(TokioMutex::new(HashMap::new()))),
next_task_id: Arc::new(Mutex::new(std::sync::atomic::AtomicU64::new(1))),
semaphore: Arc::new(Mutex::new(Semaphore::new(10))), })
}
pub async fn transfer_file_to_socket<F: AsRawFd + Send + Sync + Seek, S: AsRawFd + Send + Sync>(
&self,
file: &mut F,
socket: &mut S,
max_bytes: usize,
) -> Result<u64, ZeroCopyError> {
let start_time: _ = Instant::now();
let src_fd: _ = file.as_raw_fd();
let dst_fd: _ = socket.as_raw_fd();
let task_id: _ = self.next_task_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let task: _ = AsyncZeroCopyTask {
id: task_id,
src_fd,
dst_fd,
offset: file.seek(SeekFrom::Current(0)).unwrap_or(0),
length: max_bytes,
direction: ZeroCopyDirection::FileToSocket,
status: TaskStatus::Pending,
start_time,
end_time: None,
};
{
let mut tasks = self.active_tasks.lock().await;
tasks.insert(task_id, task);
}
let _permit: _ = self.semaphore.acquire().await.map_err(|_| {
ZeroCopyError::ResourceExhausted
})?;
let result: _ = self.execute_async_transfer(src_fd, dst_fd, max_bytes).await;
{
let mut tasks = self.active_tasks.lock().await;
if let Some(task) = tasks.get_mut(&task_id) {
task.end_time = Some(Instant::now());
match &result {
Ok(_) => task.status = TaskStatus::Completed,
Err(e) => task.status = TaskStatus::Failed(e.to_string()),
}
}
}
match result {
Ok(bytes) => {
let duration: _ = start_time.elapsed();
self.monitor.record_success(bytes, duration);
let mut stats = self.stats.lock().await;
stats.total_tasks += 1;
stats.success_tasks += 1;
stats.total_bytes += bytes;
if duration.as_micros() > 0 {
let latency_us: _ = duration.as_micros() as u64;
if stats.total_tasks == 1 {
stats.avg_latency_us = latency_us;
} else {
stats.avg_latency_us = (stats.avg_latency_us * (stats.total_tasks - 1) + latency_us)
/ stats.total_tasks;
}
}
if duration.as_secs_f64() > 0.0 {
let speed: _ = bytes as f64 / duration.as_secs_f64();
if speed > stats.peak_speed {
stats.peak_speed = speed;
}
}
println!("✅ 异步零拷贝传输成功: {} bytes, 耗时: {:?}", bytes, duration);
Ok(bytes)
}
Err(e) => {
let duration: _ = start_time.elapsed();
self.monitor.record_failure();
let mut stats = self.stats.lock().await;
stats.total_tasks += 1;
stats.failed_tasks += 1;
println!("❌ 异步零拷贝传输失败: {}, 耗时: {:?}", e, duration);
Err(e)
}
}
}
pub async fn transfer_pipe_to_socket<P: AsRawFd + Send + Sync, S: AsRawFd + Send + Sync>(
&self,
pipe: &mut P,
socket: &mut S,
max_bytes: usize,
) -> Result<u64, ZeroCopyError> {
let start_time: _ = Instant::now();
let src_fd: _ = pipe.as_raw_fd();
let dst_fd: _ = socket.as_raw_fd();
let task_id: _ = self.next_task_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let task: _ = AsyncZeroCopyTask {
id: task_id,
src_fd,
dst_fd,
offset: 0,
length: max_bytes,
direction: ZeroCopyDirection::PipeToSocket,
status: TaskStatus::Pending,
start_time,
end_time: None,
};
{
let mut tasks = self.active_tasks.lock().await;
tasks.insert(task_id, task);
}
let _permit: _ = self.semaphore.acquire().await.map_err(|_| {
ZeroCopyError::ResourceExhausted
})?;
let result: _ = self.execute_async_transfer(src_fd, dst_fd, max_bytes).await;
{
let mut tasks = self.active_tasks.lock().await;
if let Some(task) = tasks.get_mut(&task_id) {
task.end_time = Some(Instant::now());
match &result {
Ok(_) => task.status = TaskStatus::Completed,
Err(e) => task.status = TaskStatus::Failed(e.to_string()),
}
}
}
match result {
Ok(bytes) => {
let duration: _ = start_time.elapsed();
self.monitor.record_success(bytes, duration);
let mut stats = self.stats.lock().await;
stats.total_tasks += 1;
stats.success_tasks += 1;
stats.total_bytes += bytes;
if duration.as_micros() > 0 {
let latency_us: _ = duration.as_micros() as u64;
if stats.total_tasks == 1 {
stats.avg_latency_us = latency_us;
} else {
stats.avg_latency_us = (stats.avg_latency_us * (stats.total_tasks - 1) + latency_us)
/ stats.total_tasks;
}
}
if duration.as_secs_f64() > 0.0 {
let speed: _ = bytes as f64 / duration.as_secs_f64();
if speed > stats.peak_speed {
stats.peak_speed = speed;
}
}
println!("✅ 异步管道到套接字零拷贝传输成功: {} bytes, 耗时: {:?}", bytes, duration);
Ok(bytes)
}
Err(e) => {
let duration: _ = start_time.elapsed();
self.monitor.record_failure();
let mut stats = self.stats.lock().await;
stats.total_tasks += 1;
stats.failed_tasks += 1;
println!("❌ 异步管道到套接字零拷贝传输失败: {}, 耗时: {:?}", e, duration);
Err(e)
}
}
}
async fn execute_async_transfer(
&self,
src_fd: RawFd,
dst_fd: RawFd,
max_bytes: usize,
) -> Result<u64, ZeroCopyError> {
tokio::time::sleep(Duration::from_millis(1)).await;
#[cfg(unix)]
{
let chunk_size: _ = std::cmp::min(max_bytes, self.config.buffer_size);
Ok(chunk_size as u64)
}
#[cfg(not(unix))]
{
Err(ZeroCopyError::Unsupported(
"零拷贝传输仅在 Unix 系统上支持".to_string(),
))
}
}
pub async fn get_active_tasks(&self) -> HashMap<u64, AsyncZeroCopyTask> {
(*self.active_tasks.lock().await).clone()
}
pub async fn get_stats(&self) -> AsyncZeroCopyStats {
self.stats.lock().await.clone()
}
pub fn get_monitor(&self) -> Arc<ZeroCopyMonitor> {
self.monitor.clone()
}
pub async fn generate_report(&self) -> String {
let stats: _ = self.stats.lock().await;
let monitor_report: _ = self.monitor.generate_report();
format!(
r#"
异步零拷贝 I/O 性能报告
=======================
总任务数: {}
成功任务数: {}
失败任务数: {}
成功率: {:.1}%
总传输字节数: {} bytes ({:.2} MB)
平均任务延迟: {} 微秒
峰值传输速度: {:.2} bytes/sec ({:.2} MB/sec)
{}
性能提升倍数: {:.2}x
"#,
stats.total_tasks,
stats.success_tasks,
stats.failed_tasks,
if stats.total_tasks > 0 {
stats.success_tasks as f64 / stats.total_tasks as f64 * 100.0
} else {
0.0
},
stats.total_bytes,
stats.total_bytes as f64 / 1024.0 / 1024.0,
stats.avg_latency_us,
stats.peak_speed,
stats.peak_speed / 1024.0 / 1024.0,
monitor_report,
if stats.peak_speed > 0.0 {
stats.peak_speed / 1000000.0 } else {
0.0
}
)
}
pub async fn cleanup_completed_tasks(&self) {
let mut tasks = self.active_tasks.lock().await;
tasks.retain(|_, task| {
matches!(task.status, TaskStatus::Pending | TaskStatus::Running)
});
println!("🧹 清理已完成任务,剩余活跃任务数: {}", tasks.len());
}
}
impl Default for AsyncZeroCopy {
fn default() -> Self {
Self::new(None).expect("Failed to create default AsyncZeroCopy")
}
}
#[cfg(test)]
mod tests {
#[tokio::test]
async fn test_async_zero_copy_creation() {
let async_zero_copy: _ = AsyncZeroCopy::new(None).expect("创建异步零拷贝失败");
let stats: _ = async_zero_copy.get_stats().await;
assert_eq!(stats.total_tasks, 0);
assert_eq!(stats.success_tasks, 0);
assert_eq!(stats.failed_tasks, 0);
println!("✅ 测试通过: 异步零拷贝创建");
}
#[tokio::test]
async fn test_active_tasks_management() {
let async_zero_copy: _ = AsyncZeroCopy::new(None).expect("创建异步零拷贝失败");
let src_fd: _ = 0; let dst_fd: _ = 1;
let max_bytes: _ = 1024;
let result: _ = async_zero_copy.execute_async_transfer(src_fd, dst_fd, max_bytes).await;
match result {
Ok(bytes) => {
assert!(bytes > 0);
println!("传输字节数: {}", bytes);
}
Err(_) => {
}
}
println!("✅ 测试通过: 活跃任务管理");
}
#[tokio::test]
async fn test_stats_update() {
let async_zero_copy: _ = AsyncZeroCopy::new(None).expect("创建异步零拷贝失败");
let start_time: _ = Instant::now();
let bytes: _ = 1024u64;
let duration: _ = start_time.elapsed();
async_zero_copy.monitor.record_success(bytes, duration);
let stats: _ = async_zero_copy.get_stats().await;
assert_eq!(stats.success_tasks, 1);
assert_eq!(stats.total_bytes, bytes);
println!("✅ 测试通过: 统计信息更新");
}
#[tokio::test]
async fn test_performance_report() {
let async_zero_copy: _ = AsyncZeroCopy::new(None).expect("创建异步零拷贝失败");
let report: _ = async_zero_copy.generate_report().await;
assert!(!report.is_empty());
assert!(report.contains("异步零拷贝 I/O 性能报告"));
println!("报告内容:\n{}", report);
println!("✅ 测试通过: 性能报告生成");
}
}