use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};
use super::{NetworkConfig, NetworkStats};
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct UringConfig {
pub queue_depth: u32,
pub cq_size: u32,
pub enable_sq_poll: bool,
pub sq_thread_idle: u32,
pub enable_cqe32: bool,
pub enable_buffers: bool,
}
impl Default for UringConfig {
fn default() -> Self {
Self {
queue_depth: 256,
cq_size: 512,
enable_sq_poll: true,
sq_thread_idle: 1000,
enable_cqe32: false,
enable_buffers: true,
}
}
}
#[derive(Debug, Clone)]
pub struct UringSubmission {
pub opcode: u8,
pub flags: u8,
pub ioprio: u16,
pub fd: i32,
pub addr: u64,
pub len: u32,
pub offset: u64,
pub user_data: u64,
}
#[derive(Debug, Clone)]
pub struct UringCompletion {
pub user_data: u64,
pub result: i32,
pub flags: u32,
}
#[derive(Debug, Clone)]
pub struct UringStats {
pub submissions: u64,
pub completions: u64,
pub average_latency_ns: u64,
pub peak_qps: u64,
pub queue_utilization: f64,
}
pub struct IoUringEngine {
config: NetworkConfig,
uring_config: UringConfig,
stats: Arc<RwLock<UringStats>>,
active_operations: Arc<RwLock<HashMap<u64, std::time::Instant>>>,
operation_counter: Arc<RwLock<u64>>,
completion_queue: Arc<RwLock<Vec<UringCompletion>>>,
}
impl IoUringEngine {
pub fn new(config: NetworkConfig) -> Self {
let uring_config: _ = UringConfig::default();
Self {
stats: Arc::new(Mutex::new(UringStats {
submissions: 0,
completions: 0,
average_latency_ns: 0,
peak_qps: 0,
queue_utilization: 0.0,
})),
active_operations: Arc::new(Mutex::new(HashMap::new())),
operation_counter: Arc::new(Mutex::new(0)),
completion_queue: Arc::new(Mutex::new(Vec::new())),
config,
uring_config,
}
}
pub async fn initialize(&self) -> Result<(), Box<dyn std::error::Error>> {
println!("✅ io_uring 引擎初始化完成");
let completion_queue: _ = Arc::clone(&self.completion_queue);
let stats: _ = Arc::clone(&self.stats);
tokio::spawn(async move {
loop {
tokio::time::sleep(Duration::from_millis(1)).await;
let mut completions = completion_queue.write().await;
if !completions.is_empty() {
let start_time: _ = std::time::Instant::now();
for completion in completions.drain(..) {
Self::process_completion(&stats, &completion).await;
}
let elapsed: _ = start_time.elapsed();
let mut stats_guard = stats.write().await;
stats_guard.average_latency_ns = (stats_guard.average_latency_ns
+ elapsed.as_nanos() as u64) / 2;
}
}
});
Ok(())
}
pub async fn submit(&self, submission: UringSubmission) -> Result<(), Box<dyn std::error::Error>> {
let id: _ = {
let mut counter = self.operation_counter.write().await;
*counter += 1;
*counter
};
let submission_with_id: _ = UringSubmission {
user_data: id,
..submission
};
{
let mut active = self.active_operations.write().await;
active.insert(id, std::time::Instant::now());
}
self.submit_to_uring(submission_with_id).await?;
let mut stats = self.stats.write().await;
stats.submissions += 1;
stats.queue_utilization = (stats.submissions as f64 / self.uring_config.queue_depth as f64)
.min(1.0);
Ok(())
}
async fn submit_to_uring(&self, submission: UringSubmission) -> Result<(), Box<dyn std::error::Error>> {
match submission.opcode {
0 => {
println!("📝 提交 NOP 操作 (id: {})", submission.user_data);
}
1 => {
println!("📖 提交 READ 操作 (fd: {}, len: {})", submission.fd, submission.len);
self.simulate_completion(submission.user_data, submission.len as i32).await;
}
2 => {
println!("📝 提交 WRITE 操作 (fd: {}, len: {})", submission.fd, submission.len);
self.simulate_completion(submission.user_data, submission.len as i32).await;
}
_ => {
return Err(format!("不支持的操作码: {}", submission.opcode).into());
}
}
Ok(())
}
async fn simulate_completion(&self, user_data: u64, result: i32) {
let completion: _ = UringCompletion {
user_data,
result,
flags: 0,
};
let mut queue = self.completion_queue.write().await;
queue.push(completion);
}
async fn process_completion(stats: &Arc<RwLock<UringStats>>, completion: &UringCompletion) {
let mut stats_guard = stats.write().await;
stats_guard.completions += 1;
if completion.result < 0 {
println!("❌ 操作失败 (id: {}, result: {})", completion.user_data, completion.result);
} else {
println!("✅ 操作完成 (id: {}, bytes: {})", completion.user_data, completion.result);
}
}
pub async fn wait_for_completions(&self, count: usize) -> Vec<UringCompletion> {
let mut completions = Vec::with_capacity(count);
while completions.len() < count {
{
let mut queue = self.completion_queue.write().await;
if !queue.is_empty() {
completions.push(queue.remove(0));
}
}
if completions.len() < count {
tokio::time::sleep(Duration::from_micros(10)).await;
}
}
completions
}
pub async fn get_stats(&self) -> UringStats {
self.stats.read().await.clone()
}
pub async fn get_active_operations_count(&self) -> usize {
self.active_operations.read().await.len()
}
pub async fn shutdown(&self) -> Result<(), Box<dyn std::error::Error>> {
println!("🔄 io_uring 引擎已关闭");
Ok(())
}
}
impl Drop for IoUringEngine {
fn drop(&mut self) {
let temp_file: _ = std::env::temp_dir()
.join(format!("amberjs_io_uring_{}", std::process::id()));
let _: _ = std::fs::remove_file(temp_file);
}
}