Files
sol-trade-sdk/src/perf/ultra_low_latency.rs
T

600 lines
20 KiB
Rust
Raw Normal View History

2025-10-06 23:40:27 +08:00
//! 🚀 超低延迟优化模块 - 目标实现<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);
}
}