mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-08-18 03:18:05 +00:00
perf: Major event processing system refactor for improved performance
This commit is contained in:
@@ -11,4 +11,4 @@ pub const DEFAULT_BATCH_TIMEOUT_MS: u64 = 5;
|
||||
// 性能监控相关常量
|
||||
pub const DEFAULT_METRICS_WINDOW_SECONDS: u64 = 5;
|
||||
pub const DEFAULT_METRICS_PRINT_INTERVAL_SECONDS: u64 = 10;
|
||||
pub const SLOW_PROCESSING_THRESHOLD_US: f64 = 500.0;
|
||||
pub const SLOW_PROCESSING_THRESHOLD_US: f64 = 3000.0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::Signature;
|
||||
|
||||
use crate::common::AnyResult;
|
||||
use crate::streaming::common::{
|
||||
@@ -14,7 +14,7 @@ use crate::streaming::event_parser::EventParser;
|
||||
use crate::streaming::event_parser::{
|
||||
core::traits::UnifiedEvent, protocols::mutil::parser::MutilEventParser, Protocol,
|
||||
};
|
||||
use crate::streaming::grpc::{BackpressureStrategy, BatchConfig, EventPretty};
|
||||
use crate::streaming::grpc::{BackpressureConfig, BatchConfig, EventPretty};
|
||||
use crate::streaming::shred::TransactionWithSlot;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
@@ -25,21 +25,24 @@ pub struct EventProcessor {
|
||||
pub(crate) parser_cache: OnceCell<Arc<dyn EventParser>>,
|
||||
pub(crate) protocols: Vec<Protocol>,
|
||||
pub(crate) event_type_filter: Option<EventTypeFilter>,
|
||||
pub(crate) backpressure_strategy: BackpressureStrategy,
|
||||
pub(crate) callback: Option<Arc<dyn Fn(Box<dyn UnifiedEvent>) + Send + Sync>>,
|
||||
pub(crate) backpressure_config: BackpressureConfig,
|
||||
pub(crate) batch_config: BatchConfig,
|
||||
}
|
||||
|
||||
impl EventProcessor {
|
||||
/// 创建新的事件处理器
|
||||
pub fn new(metrics_manager: MetricsManager, config: ClientConfig) -> Self {
|
||||
let backpressure_config = config.backpressure.clone();
|
||||
Self {
|
||||
metrics_manager,
|
||||
config,
|
||||
parser_cache: OnceCell::new(),
|
||||
protocols: vec![],
|
||||
event_type_filter: None,
|
||||
backpressure_strategy: BackpressureStrategy::Block,
|
||||
backpressure_config,
|
||||
batch_config: BatchConfig::default(),
|
||||
callback: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,13 +50,15 @@ impl EventProcessor {
|
||||
&mut self,
|
||||
protocols: Vec<Protocol>,
|
||||
event_type_filter: Option<EventTypeFilter>,
|
||||
backpressure_strategy: BackpressureStrategy,
|
||||
backpressure_config: BackpressureConfig,
|
||||
batch_config: BatchConfig,
|
||||
callback: Option<Arc<dyn Fn(Box<dyn UnifiedEvent>) + Send + Sync>>,
|
||||
) {
|
||||
self.protocols = protocols.clone();
|
||||
self.event_type_filter = event_type_filter.clone();
|
||||
self.backpressure_strategy = backpressure_strategy;
|
||||
self.backpressure_config = backpressure_config;
|
||||
self.batch_config = batch_config;
|
||||
self.callback = callback;
|
||||
self.parser_cache
|
||||
.get_or_init(|| Arc::new(MutilEventParser::new(protocols, event_type_filter)));
|
||||
}
|
||||
@@ -62,35 +67,24 @@ impl EventProcessor {
|
||||
self.parser_cache.get().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn get_event_handle(&self) -> Option<JoinHandle<()>> {
|
||||
return None;
|
||||
}
|
||||
|
||||
pub async fn process_grpc_event_transaction_with_metrics<F>(
|
||||
pub async fn process_grpc_event_transaction_with_metrics(
|
||||
&self,
|
||||
event_pretty: EventPretty,
|
||||
callback: &F,
|
||||
bot_wallet: Option<Pubkey>,
|
||||
) -> AnyResult<()>
|
||||
where
|
||||
F: Fn(Box<dyn UnifiedEvent>) + Send + Sync,
|
||||
{
|
||||
self.process_grpc_event_transaction(event_pretty, callback, bot_wallet).await?;
|
||||
) -> AnyResult<()> {
|
||||
self.process_grpc_event_transaction(event_pretty, bot_wallet).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn process_grpc_event_transaction<F>(
|
||||
async fn process_grpc_event_transaction(
|
||||
&self,
|
||||
event_pretty: EventPretty,
|
||||
callback: &F,
|
||||
bot_wallet: Option<Pubkey>,
|
||||
) -> AnyResult<()>
|
||||
where
|
||||
F: Fn(Box<dyn UnifiedEvent>) + Send + Sync,
|
||||
{
|
||||
) -> AnyResult<()> {
|
||||
match event_pretty {
|
||||
EventPretty::Account(account_pretty) => {
|
||||
self.metrics_manager.add_account_process_count();
|
||||
let signature = account_pretty.signature;
|
||||
let account_event = AccountEventParser::parse_account_event(
|
||||
self.protocols.clone(),
|
||||
account_pretty,
|
||||
@@ -98,12 +92,12 @@ impl EventProcessor {
|
||||
);
|
||||
if let Some(event) = account_event {
|
||||
let processing_time_us = event.program_handle_time_consuming_us() as f64;
|
||||
callback(event);
|
||||
// 更新性能指标(如果启用)
|
||||
self.metrics_manager.update_metrics(
|
||||
self.invoke_callback(event);
|
||||
self.update_metrics(
|
||||
MetricsEventType::Account,
|
||||
1,
|
||||
processing_time_us,
|
||||
Some(signature),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -113,7 +107,7 @@ impl EventProcessor {
|
||||
let signature = transaction_pretty.signature;
|
||||
// 使用缓存获取解析器
|
||||
let parser = self.get_parser();
|
||||
let mut all_events = parser
|
||||
let all_events = parser
|
||||
.parse_transaction(
|
||||
transaction_pretty.tx.clone(),
|
||||
signature,
|
||||
@@ -125,37 +119,26 @@ impl EventProcessor {
|
||||
.await
|
||||
.unwrap_or_else(|_e| vec![]);
|
||||
|
||||
// 为所有事件设置交易索引
|
||||
for event in &mut all_events {
|
||||
event.set_transaction_index(transaction_pretty.transaction_index);
|
||||
}
|
||||
|
||||
let max_time_consuming_us = all_events
|
||||
.iter()
|
||||
.map(|event| event.program_handle_time_consuming_us())
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
// 保存事件数量用于日志记录
|
||||
let mut max_time_consuming_us = 0;
|
||||
let event_count = all_events.len();
|
||||
|
||||
// 批量处理事件
|
||||
if !all_events.is_empty() {
|
||||
for mut event in all_events {
|
||||
event.set_program_handle_time_consuming_us(
|
||||
chrono::Utc::now().timestamp_micros()
|
||||
- event.program_received_time_us(),
|
||||
);
|
||||
callback(event);
|
||||
}
|
||||
// 为所有事件设置交易索引
|
||||
for mut event in all_events {
|
||||
event.set_transaction_index(transaction_pretty.transaction_index);
|
||||
event.set_program_handle_time_consuming_us(
|
||||
chrono::Utc::now().timestamp_micros() - event.program_received_time_us(),
|
||||
);
|
||||
max_time_consuming_us =
|
||||
max_time_consuming_us.max(event.program_handle_time_consuming_us());
|
||||
self.invoke_callback(event);
|
||||
}
|
||||
|
||||
// 更新性能指标
|
||||
// 更新性能指标(如果启用)
|
||||
self.metrics_manager.update_metrics(
|
||||
MetricsEventType::Tx,
|
||||
self.update_metrics(
|
||||
MetricsEventType::Transaction,
|
||||
event_count as u64,
|
||||
max_time_consuming_us as f64,
|
||||
Some(signature),
|
||||
);
|
||||
}
|
||||
EventPretty::BlockMeta(block_meta_pretty) => {
|
||||
@@ -171,29 +154,34 @@ impl EventProcessor {
|
||||
block_meta_pretty.program_received_time_us,
|
||||
);
|
||||
let processing_time_us = block_meta_event.program_handle_time_consuming_us() as f64;
|
||||
callback(block_meta_event);
|
||||
// 更新性能指标(如果启用)
|
||||
self.metrics_manager.update_metrics(
|
||||
MetricsEventType::BlockMeta,
|
||||
1,
|
||||
processing_time_us,
|
||||
);
|
||||
self.invoke_callback(block_meta_event);
|
||||
self.update_metrics(MetricsEventType::BlockMeta, 1, processing_time_us, None);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn invoke_callback(&self, event: Box<dyn UnifiedEvent>) {
|
||||
if let Some(callback) = self.callback.as_ref() {
|
||||
callback(event);
|
||||
}
|
||||
}
|
||||
|
||||
/// 即时处理单个交易
|
||||
pub async fn process_shred_transaction_immediate<F>(
|
||||
pub async fn process_shred_transaction_immediate(
|
||||
&self,
|
||||
transaction_with_slot: TransactionWithSlot,
|
||||
bot_wallet: Option<Pubkey>,
|
||||
callback: &F,
|
||||
) -> AnyResult<()>
|
||||
where
|
||||
F: Fn(Box<dyn UnifiedEvent>) + Send + Sync,
|
||||
{
|
||||
) -> AnyResult<()> {
|
||||
self.process_shred_transaction(transaction_with_slot, bot_wallet).await
|
||||
}
|
||||
|
||||
pub async fn process_shred_transaction(
|
||||
&self,
|
||||
transaction_with_slot: TransactionWithSlot,
|
||||
bot_wallet: Option<Pubkey>,
|
||||
) -> AnyResult<()> {
|
||||
self.metrics_manager.add_tx_process_count();
|
||||
let program_received_time_us = chrono::Utc::now().timestamp_micros();
|
||||
let slot = transaction_with_slot.slot;
|
||||
@@ -215,11 +203,7 @@ impl EventProcessor {
|
||||
.await
|
||||
.unwrap_or_else(|_e| vec![]);
|
||||
|
||||
let max_time_consuming_us = all_events
|
||||
.iter()
|
||||
.map(|event| event.program_handle_time_consuming_us())
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
let mut max_time_consuming_us = 0;
|
||||
|
||||
// 保存事件数量用于日志记录
|
||||
let event_count = all_events.len();
|
||||
@@ -229,18 +213,31 @@ impl EventProcessor {
|
||||
event.set_program_handle_time_consuming_us(
|
||||
chrono::Utc::now().timestamp_micros() - event.program_received_time_us(),
|
||||
);
|
||||
callback(event);
|
||||
max_time_consuming_us =
|
||||
max_time_consuming_us.max(event.program_handle_time_consuming_us());
|
||||
self.invoke_callback(event);
|
||||
}
|
||||
|
||||
// 实际调用性能指标更新
|
||||
self.metrics_manager.update_metrics(
|
||||
MetricsEventType::Tx,
|
||||
self.update_metrics(
|
||||
MetricsEventType::Transaction,
|
||||
event_count as u64,
|
||||
max_time_consuming_us as f64,
|
||||
Some(signature),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_metrics(
|
||||
&self,
|
||||
ty: MetricsEventType,
|
||||
count: u64,
|
||||
time_us: f64,
|
||||
signature: Option<Signature>,
|
||||
) {
|
||||
self.metrics_manager.update_metrics(ty, count, time_us, signature);
|
||||
}
|
||||
}
|
||||
|
||||
// 实现 Clone trait 以支持模块间共享
|
||||
@@ -252,8 +249,9 @@ impl Clone for EventProcessor {
|
||||
parser_cache: self.parser_cache.clone(),
|
||||
protocols: self.protocols.clone(),
|
||||
event_type_filter: self.event_type_filter.clone(),
|
||||
backpressure_strategy: self.backpressure_strategy.clone(),
|
||||
backpressure_config: self.backpressure_config.clone(),
|
||||
batch_config: self.batch_config.clone(),
|
||||
callback: self.callback.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+453
-242
@@ -1,344 +1,554 @@
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use crossbeam::utils::Backoff;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use std::sync::RwLock;
|
||||
|
||||
use super::config::StreamClientConfig;
|
||||
use solana_sdk::signature::Signature;
|
||||
|
||||
use super::constants::*;
|
||||
|
||||
/// 单个事件类型的指标
|
||||
/// 事件类型枚举
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum EventType {
|
||||
Transaction = 0,
|
||||
Account = 1,
|
||||
BlockMeta = 2,
|
||||
}
|
||||
|
||||
/// 兼容性别名
|
||||
pub type MetricsEventType = EventType;
|
||||
|
||||
impl EventType {
|
||||
#[inline]
|
||||
const fn as_index(self) -> usize {
|
||||
self as usize
|
||||
}
|
||||
|
||||
const fn name(self) -> &'static str {
|
||||
match self {
|
||||
EventType::Transaction => "TX",
|
||||
EventType::Account => "Account",
|
||||
EventType::BlockMeta => "Block Meta",
|
||||
}
|
||||
}
|
||||
|
||||
// 兼容性常量
|
||||
pub const TX: EventType = EventType::Transaction;
|
||||
}
|
||||
|
||||
/// 高性能原子事件指标
|
||||
#[derive(Debug)]
|
||||
struct AtomicEventMetrics {
|
||||
process_count: AtomicU64,
|
||||
events_processed: AtomicU64,
|
||||
events_in_window: AtomicU64,
|
||||
window_start_nanos: AtomicU64,
|
||||
events_per_second_bits: AtomicU64, // f64 的位表示
|
||||
}
|
||||
|
||||
impl AtomicEventMetrics {
|
||||
fn new(now_nanos: u64) -> Self {
|
||||
Self {
|
||||
process_count: AtomicU64::new(0),
|
||||
events_processed: AtomicU64::new(0),
|
||||
events_in_window: AtomicU64::new(0),
|
||||
window_start_nanos: AtomicU64::new(now_nanos),
|
||||
events_per_second_bits: AtomicU64::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
/// 原子地增加处理计数
|
||||
#[inline]
|
||||
fn add_process_count(&self) {
|
||||
self.process_count.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 原子地增加事件处理数量
|
||||
#[inline]
|
||||
fn add_events_processed(&self, count: u64) {
|
||||
self.events_processed.fetch_add(count, Ordering::Relaxed);
|
||||
self.events_in_window.fetch_add(count, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 获取当前计数(非阻塞)
|
||||
#[inline]
|
||||
fn get_counts(&self) -> (u64, u64, u64) {
|
||||
(
|
||||
self.process_count.load(Ordering::Relaxed),
|
||||
self.events_processed.load(Ordering::Relaxed),
|
||||
self.events_in_window.load(Ordering::Relaxed),
|
||||
)
|
||||
}
|
||||
|
||||
/// 原子地更新每秒事件数
|
||||
#[inline]
|
||||
fn update_events_per_second(&self, eps: f64) {
|
||||
self.events_per_second_bits.store(eps.to_bits(), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 获取每秒事件数
|
||||
#[inline]
|
||||
fn get_events_per_second(&self) -> f64 {
|
||||
f64::from_bits(self.events_per_second_bits.load(Ordering::Relaxed))
|
||||
}
|
||||
|
||||
/// 重置窗口计数
|
||||
#[inline]
|
||||
fn reset_window(&self, new_start_nanos: u64) {
|
||||
self.events_in_window.store(0, Ordering::Relaxed);
|
||||
self.window_start_nanos.store(new_start_nanos, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_window_start(&self) -> u64 {
|
||||
self.window_start_nanos.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
/// 高性能原子处理时间统计
|
||||
#[derive(Debug)]
|
||||
struct AtomicProcessingTimeStats {
|
||||
min_time_bits: AtomicU64,
|
||||
max_time_bits: AtomicU64,
|
||||
total_time_us: AtomicU64, // 存储微秒的整数部分
|
||||
total_events: AtomicU64,
|
||||
}
|
||||
|
||||
impl AtomicProcessingTimeStats {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
min_time_bits: AtomicU64::new(f64::INFINITY.to_bits()),
|
||||
max_time_bits: AtomicU64::new(0),
|
||||
total_time_us: AtomicU64::new(0),
|
||||
total_events: AtomicU64::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
/// 原子地更新处理时间统计
|
||||
#[inline]
|
||||
fn update(&self, time_us: f64, event_count: u64) {
|
||||
let time_bits = time_us.to_bits();
|
||||
|
||||
// 更新最小值(使用 compare_exchange_weak 循环)
|
||||
let mut current_min = self.min_time_bits.load(Ordering::Relaxed);
|
||||
while time_bits < current_min {
|
||||
match self.min_time_bits.compare_exchange_weak(
|
||||
current_min,
|
||||
time_bits,
|
||||
Ordering::Relaxed,
|
||||
Ordering::Relaxed,
|
||||
) {
|
||||
Ok(_) => break,
|
||||
Err(x) => current_min = x,
|
||||
}
|
||||
}
|
||||
|
||||
// 更新最大值
|
||||
let mut current_max = self.max_time_bits.load(Ordering::Relaxed);
|
||||
while time_bits > current_max {
|
||||
match self.max_time_bits.compare_exchange_weak(
|
||||
current_max,
|
||||
time_bits,
|
||||
Ordering::Relaxed,
|
||||
Ordering::Relaxed,
|
||||
) {
|
||||
Ok(_) => break,
|
||||
Err(x) => current_max = x,
|
||||
}
|
||||
}
|
||||
|
||||
// 更新累计值(将微秒转换为整数避免浮点累加问题)
|
||||
let total_time_us_int = (time_us * event_count as f64) as u64;
|
||||
self.total_time_us.fetch_add(total_time_us_int, Ordering::Relaxed);
|
||||
self.total_events.fetch_add(event_count, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// 获取统计值(非阻塞)
|
||||
#[inline]
|
||||
fn get_stats(&self) -> ProcessingTimeStats {
|
||||
let min_bits = self.min_time_bits.load(Ordering::Relaxed);
|
||||
let max_bits = self.max_time_bits.load(Ordering::Relaxed);
|
||||
let total_time_us_int = self.total_time_us.load(Ordering::Relaxed);
|
||||
let total_events = self.total_events.load(Ordering::Relaxed);
|
||||
|
||||
let min_time = f64::from_bits(min_bits);
|
||||
let max_time = f64::from_bits(max_bits);
|
||||
let avg_time =
|
||||
if total_events > 0 { total_time_us_int as f64 / total_events as f64 } else { 0.0 };
|
||||
|
||||
ProcessingTimeStats {
|
||||
min_us: if min_time == f64::INFINITY { 0.0 } else { min_time },
|
||||
max_us: max_time,
|
||||
avg_us: avg_time,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理时间统计结果
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EventMetrics {
|
||||
pub struct ProcessingTimeStats {
|
||||
pub min_us: f64,
|
||||
pub max_us: f64,
|
||||
pub avg_us: f64,
|
||||
}
|
||||
|
||||
/// 事件指标快照
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EventMetricsSnapshot {
|
||||
pub process_count: u64,
|
||||
pub events_processed: u64,
|
||||
pub events_per_second: f64,
|
||||
pub events_in_window: u64,
|
||||
pub window_start_time: std::time::Instant,
|
||||
}
|
||||
|
||||
impl EventMetrics {
|
||||
fn new(now: std::time::Instant) -> Self {
|
||||
Self {
|
||||
process_count: 0,
|
||||
events_processed: 0,
|
||||
events_per_second: 0.0,
|
||||
events_in_window: 0,
|
||||
window_start_time: now,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 通用性能监控指标
|
||||
/// 兼容性结构 - 完整的性能指标
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PerformanceMetrics {
|
||||
pub start_time: std::time::Instant,
|
||||
pub event_metrics: [EventMetrics; 3], // [Tx, Account, BlockMeta]
|
||||
pub average_processing_time_us: f64,
|
||||
pub min_processing_time_us: f64,
|
||||
pub max_processing_time_us: f64,
|
||||
pub last_update_time: std::time::Instant,
|
||||
}
|
||||
|
||||
impl Default for PerformanceMetrics {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MetricsEventType {
|
||||
Tx,
|
||||
Account,
|
||||
BlockMeta,
|
||||
}
|
||||
|
||||
impl MetricsEventType {
|
||||
fn as_index(&self) -> usize {
|
||||
match self {
|
||||
MetricsEventType::Tx => 0,
|
||||
MetricsEventType::Account => 1,
|
||||
MetricsEventType::BlockMeta => 2,
|
||||
}
|
||||
}
|
||||
pub uptime: std::time::Duration,
|
||||
pub tx_metrics: EventMetricsSnapshot,
|
||||
pub account_metrics: EventMetricsSnapshot,
|
||||
pub block_meta_metrics: EventMetricsSnapshot,
|
||||
pub processing_stats: ProcessingTimeStats,
|
||||
}
|
||||
|
||||
impl PerformanceMetrics {
|
||||
/// 创建默认的性能指标(兼容性方法)
|
||||
pub fn new() -> Self {
|
||||
let now = std::time::Instant::now();
|
||||
let default_metrics =
|
||||
EventMetricsSnapshot { process_count: 0, events_processed: 0, events_per_second: 0.0 };
|
||||
let default_stats = ProcessingTimeStats { min_us: 0.0, max_us: 0.0, avg_us: 0.0 };
|
||||
|
||||
Self {
|
||||
start_time: now,
|
||||
event_metrics: [EventMetrics::new(now), EventMetrics::new(now), EventMetrics::new(now)],
|
||||
average_processing_time_us: 0.0,
|
||||
min_processing_time_us: 0.0,
|
||||
max_processing_time_us: 0.0,
|
||||
last_update_time: now,
|
||||
uptime: std::time::Duration::ZERO,
|
||||
tx_metrics: default_metrics.clone(),
|
||||
account_metrics: default_metrics.clone(),
|
||||
block_meta_metrics: default_metrics,
|
||||
processing_stats: default_stats,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 高性能指标系统
|
||||
#[derive(Debug)]
|
||||
pub struct HighPerformanceMetrics {
|
||||
start_nanos: u64,
|
||||
event_metrics: [AtomicEventMetrics; 3],
|
||||
processing_stats: AtomicProcessingTimeStats,
|
||||
}
|
||||
|
||||
impl HighPerformanceMetrics {
|
||||
fn new() -> Self {
|
||||
let now_nanos =
|
||||
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos()
|
||||
as u64;
|
||||
|
||||
Self {
|
||||
start_nanos: now_nanos,
|
||||
event_metrics: [
|
||||
AtomicEventMetrics::new(now_nanos),
|
||||
AtomicEventMetrics::new(now_nanos),
|
||||
AtomicEventMetrics::new(now_nanos),
|
||||
],
|
||||
processing_stats: AtomicProcessingTimeStats::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 更新时间窗口指标
|
||||
fn update_window_metrics(
|
||||
&mut self,
|
||||
event_type: &MetricsEventType,
|
||||
now: std::time::Instant,
|
||||
window_duration: std::time::Duration,
|
||||
) {
|
||||
/// 获取运行时长(秒)
|
||||
#[inline]
|
||||
pub fn get_uptime_seconds(&self) -> f64 {
|
||||
let now_nanos =
|
||||
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos()
|
||||
as u64;
|
||||
(now_nanos - self.start_nanos) as f64 / 1_000_000_000.0
|
||||
}
|
||||
|
||||
/// 获取事件指标快照
|
||||
#[inline]
|
||||
pub fn get_event_metrics(&self, event_type: EventType) -> EventMetricsSnapshot {
|
||||
let index = event_type.as_index();
|
||||
let event_metric = &mut self.event_metrics[index];
|
||||
let (process_count, events_processed, _) = self.event_metrics[index].get_counts();
|
||||
let events_per_second = self.calculate_real_time_eps(event_type);
|
||||
|
||||
if now.duration_since(event_metric.window_start_time) >= window_duration {
|
||||
let window_seconds = now.duration_since(event_metric.window_start_time).as_secs_f64();
|
||||
// 修复:正确计算每秒事件数,避免除零错误
|
||||
event_metric.events_per_second = if window_seconds > 0.001 {
|
||||
// 避免极小的时间差
|
||||
event_metric.events_in_window as f64 / window_seconds
|
||||
} else {
|
||||
0.0 // 时间太短时设为0,而不是事件总数
|
||||
};
|
||||
|
||||
// 重置窗口
|
||||
event_metric.events_in_window = 0;
|
||||
event_metric.window_start_time = now;
|
||||
}
|
||||
EventMetricsSnapshot { process_count, events_processed, events_per_second }
|
||||
}
|
||||
|
||||
/// 计算实时每秒事件数(用于显示)
|
||||
fn calculate_real_time_events_per_second(
|
||||
&self,
|
||||
event_type: &MetricsEventType,
|
||||
now: std::time::Instant,
|
||||
) -> f64 {
|
||||
/// 获取处理时间统计
|
||||
#[inline]
|
||||
pub fn get_processing_stats(&self) -> ProcessingTimeStats {
|
||||
self.processing_stats.get_stats()
|
||||
}
|
||||
|
||||
/// 计算实时每秒事件数(非阻塞)
|
||||
fn calculate_real_time_eps(&self, event_type: EventType) -> f64 {
|
||||
let now_nanos =
|
||||
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos()
|
||||
as u64;
|
||||
|
||||
let index = event_type.as_index();
|
||||
let event_metric = &self.event_metrics[index];
|
||||
|
||||
let current_window_duration =
|
||||
now.duration_since(event_metric.window_start_time).as_secs_f64();
|
||||
let window_start = event_metric.get_window_start();
|
||||
let current_window_duration_secs =
|
||||
(now_nanos.saturating_sub(window_start)) as f64 / 1_000_000_000.0;
|
||||
let events_in_window = event_metric.events_in_window.load(Ordering::Relaxed);
|
||||
|
||||
// 如果当前窗口有足够的时间和事件,使用当前窗口的数据
|
||||
if current_window_duration > 1.0 && event_metric.events_in_window > 0 {
|
||||
event_metric.events_in_window as f64 / current_window_duration
|
||||
// 优先级1: 当前窗口实时数据(≥2秒且有事件)
|
||||
if current_window_duration_secs >= 2.0 && events_in_window > 0 {
|
||||
return events_in_window as f64 / current_window_duration_secs;
|
||||
}
|
||||
// 如果当前窗口时间太短或没有事件,使用上一个完整窗口的值
|
||||
else if event_metric.events_per_second > 0.0 {
|
||||
event_metric.events_per_second
|
||||
|
||||
// 优先级2: 上一个窗口的结果
|
||||
let stored_eps = event_metric.get_events_per_second();
|
||||
if stored_eps > 0.0 {
|
||||
return stored_eps;
|
||||
}
|
||||
// 如果都没有,计算总体平均值
|
||||
else {
|
||||
let total_duration = now.duration_since(self.start_time).as_secs_f64();
|
||||
if total_duration > 1.0 && event_metric.events_processed > 0 {
|
||||
event_metric.events_processed as f64 / total_duration
|
||||
} else {
|
||||
0.0
|
||||
|
||||
// 优先级3: 总体平均值(≥3秒运行时间)
|
||||
let total_duration_secs = self.get_uptime_seconds();
|
||||
let total_events = event_metric.events_processed.load(Ordering::Relaxed);
|
||||
if total_duration_secs >= 3.0 && total_events > 0 {
|
||||
return total_events as f64 / total_duration_secs;
|
||||
}
|
||||
|
||||
0.0
|
||||
}
|
||||
|
||||
/// 更新窗口指标(后台任务调用)
|
||||
fn update_window_metrics(&self, event_type: EventType, window_duration_nanos: u64) {
|
||||
let now_nanos =
|
||||
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos()
|
||||
as u64;
|
||||
|
||||
let index = event_type.as_index();
|
||||
let event_metric = &self.event_metrics[index];
|
||||
|
||||
let window_start = event_metric.get_window_start();
|
||||
if now_nanos.saturating_sub(window_start) >= window_duration_nanos {
|
||||
let events_in_window = event_metric.events_in_window.load(Ordering::Relaxed);
|
||||
let window_duration_secs = window_duration_nanos as f64 / 1_000_000_000.0;
|
||||
|
||||
if window_duration_secs > 0.001 && events_in_window > 0 {
|
||||
let eps = events_in_window as f64 / window_duration_secs;
|
||||
event_metric.update_events_per_second(eps);
|
||||
}
|
||||
|
||||
event_metric.reset_window(now_nanos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 通用性能监控管理器
|
||||
/// 高性能指标管理器
|
||||
pub struct MetricsManager {
|
||||
metrics: Arc<RwLock<PerformanceMetrics>>,
|
||||
config: Arc<StreamClientConfig>,
|
||||
metrics: Arc<HighPerformanceMetrics>,
|
||||
enable_metrics: bool,
|
||||
stream_name: String,
|
||||
background_task_running: AtomicBool,
|
||||
}
|
||||
|
||||
impl MetricsManager {
|
||||
/// 创建新的性能监控管理器
|
||||
pub fn new(
|
||||
metrics: Arc<RwLock<PerformanceMetrics>>,
|
||||
config: Arc<StreamClientConfig>,
|
||||
stream_name: String,
|
||||
) -> Self {
|
||||
Self { metrics, config, stream_name }
|
||||
/// 创建新的指标管理器
|
||||
pub fn new(enable_metrics: bool, stream_name: String) -> Self {
|
||||
let manager = Self {
|
||||
metrics: Arc::new(HighPerformanceMetrics::new()),
|
||||
enable_metrics,
|
||||
stream_name,
|
||||
background_task_running: AtomicBool::new(false),
|
||||
};
|
||||
|
||||
// 启动后台任务
|
||||
manager.start_background_tasks();
|
||||
manager
|
||||
}
|
||||
|
||||
/// 获取性能指标
|
||||
pub fn get_metrics(&self) -> PerformanceMetrics {
|
||||
// 使用 Backoff 策略进行读取尝试
|
||||
let backoff = Backoff::new();
|
||||
loop {
|
||||
match self.metrics.read() {
|
||||
Ok(metrics) => return metrics.clone(),
|
||||
Err(_) => {
|
||||
// 如果获取读锁失败,使用指数退避策略
|
||||
backoff.snooze();
|
||||
continue;
|
||||
}
|
||||
/// 启动后台任务
|
||||
fn start_background_tasks(&self) {
|
||||
if self
|
||||
.background_task_running
|
||||
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_ok()
|
||||
{
|
||||
if !self.enable_metrics {
|
||||
return;
|
||||
}
|
||||
|
||||
let metrics = self.metrics.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut interval = tokio::time::interval(std::time::Duration::from_millis(500));
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
let window_duration_nanos = DEFAULT_METRICS_WINDOW_SECONDS * 1_000_000_000;
|
||||
|
||||
// 更新所有事件类型的窗口指标
|
||||
metrics.update_window_metrics(EventType::Transaction, window_duration_nanos);
|
||||
metrics.update_window_metrics(EventType::Account, window_duration_nanos);
|
||||
metrics.update_window_metrics(EventType::BlockMeta, window_duration_nanos);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// 打印性能指标
|
||||
pub fn print_metrics(&self) {
|
||||
let metrics = self.get_metrics();
|
||||
let event_names = ["TX", "Account", "Block Meta"];
|
||||
let event_types =
|
||||
[MetricsEventType::Tx, MetricsEventType::Account, MetricsEventType::BlockMeta];
|
||||
let now = std::time::Instant::now();
|
||||
/// 记录处理次数(非阻塞)
|
||||
#[inline]
|
||||
pub fn record_process(&self, event_type: EventType) {
|
||||
if self.enable_metrics {
|
||||
self.metrics.event_metrics[event_type.as_index()].add_process_count();
|
||||
}
|
||||
}
|
||||
|
||||
/// 记录事件处理(非阻塞)
|
||||
#[inline]
|
||||
pub fn record_events(&self, event_type: EventType, count: u64, processing_time_us: f64) {
|
||||
if !self.enable_metrics {
|
||||
return;
|
||||
}
|
||||
|
||||
// 原子更新事件计数
|
||||
self.metrics.event_metrics[event_type.as_index()].add_events_processed(count);
|
||||
|
||||
// 原子更新处理时间统计
|
||||
self.metrics.processing_stats.update(processing_time_us, count);
|
||||
}
|
||||
|
||||
/// 记录慢处理操作
|
||||
#[inline]
|
||||
pub fn log_slow_processing(
|
||||
&self,
|
||||
processing_time_us: f64,
|
||||
event_count: usize,
|
||||
signature: Option<Signature>,
|
||||
) {
|
||||
if processing_time_us > SLOW_PROCESSING_THRESHOLD_US {
|
||||
log::warn!(
|
||||
"{} slow processing: {:.2}us for {} events, signature: {:?}",
|
||||
self.stream_name,
|
||||
processing_time_us,
|
||||
event_count,
|
||||
signature
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取运行时长
|
||||
pub fn get_uptime(&self) -> std::time::Duration {
|
||||
std::time::Duration::from_secs_f64(self.metrics.get_uptime_seconds())
|
||||
}
|
||||
|
||||
/// 获取事件指标
|
||||
pub fn get_event_metrics(&self, event_type: EventType) -> EventMetricsSnapshot {
|
||||
self.metrics.get_event_metrics(event_type)
|
||||
}
|
||||
|
||||
/// 获取处理时间统计
|
||||
pub fn get_processing_stats(&self) -> ProcessingTimeStats {
|
||||
self.metrics.get_processing_stats()
|
||||
}
|
||||
|
||||
/// 打印性能指标(非阻塞)
|
||||
pub fn print_metrics(&self) {
|
||||
println!("\n📊 {} Performance Metrics", self.stream_name);
|
||||
println!(" Run Time: {:?}", metrics.start_time.elapsed());
|
||||
|
||||
// 打印表格头部
|
||||
println!(" Run Time: {:?}", self.get_uptime());
|
||||
|
||||
// 打印事件指标表格
|
||||
println!("┌─────────────┬──────────────┬──────────────────┬─────────────────┐");
|
||||
println!("│ Event Type │ Process Count│ Events Processed │ Events/Second │");
|
||||
println!("├─────────────┼──────────────┼──────────────────┼─────────────────┤");
|
||||
|
||||
// 打印每种事件类型的数据
|
||||
for (i, name) in event_names.iter().enumerate() {
|
||||
let event_metric = &metrics.event_metrics[i];
|
||||
// 使用实时计算的每秒事件数,而不是窗口更新的值
|
||||
let real_time_eps = metrics.calculate_real_time_events_per_second(&event_types[i], now);
|
||||
|
||||
for event_type in [EventType::Transaction, EventType::Account, EventType::BlockMeta] {
|
||||
let metrics = self.get_event_metrics(event_type);
|
||||
println!(
|
||||
"│ {:11} │ {:12} │ {:16} │ {:13.2} │",
|
||||
name,
|
||||
event_metric.process_count,
|
||||
event_metric.events_processed,
|
||||
real_time_eps
|
||||
event_type.name(),
|
||||
metrics.process_count,
|
||||
metrics.events_processed,
|
||||
metrics.events_per_second
|
||||
);
|
||||
}
|
||||
|
||||
println!("└─────────────┴──────────────┴──────────────────┴─────────────────┘");
|
||||
|
||||
// 打印处理时间统计表格
|
||||
let stats = self.get_processing_stats();
|
||||
println!("\n⏱️ Processing Time Statistics");
|
||||
println!("┌─────────────────────┬─────────────┐");
|
||||
println!("│ Metric │ Value (us) │");
|
||||
println!("├─────────────────────┼─────────────┤");
|
||||
println!("│ Average │ {:9.2} │", metrics.average_processing_time_us);
|
||||
println!("│ Minimum │ {:9.2} │", metrics.min_processing_time_us);
|
||||
println!("│ Maximum │ {:9.2} │", metrics.max_processing_time_us);
|
||||
println!("│ Average │ {:9.2} │", stats.avg_us);
|
||||
println!("│ Minimum │ {:9.2} │", stats.min_us);
|
||||
println!("│ Maximum │ {:9.2} │", stats.max_us);
|
||||
println!("└─────────────────────┴─────────────┘");
|
||||
println!();
|
||||
}
|
||||
|
||||
/// 启动自动性能监控任务
|
||||
pub async fn start_auto_monitoring(&self) -> Option<tokio::task::JoinHandle<()>> {
|
||||
// 检查是否启用性能监控
|
||||
if !self.config.enable_metrics {
|
||||
return None; // 如果未启用性能监控,不启动监控任务
|
||||
if !self.enable_metrics {
|
||||
return None;
|
||||
}
|
||||
|
||||
let metrics_manager = self.clone();
|
||||
let manager = self.clone();
|
||||
let handle = tokio::spawn(async move {
|
||||
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(
|
||||
let mut interval = tokio::time::interval(std::time::Duration::from_secs(
|
||||
DEFAULT_METRICS_PRINT_INTERVAL_SECONDS,
|
||||
));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
metrics_manager.print_metrics();
|
||||
manager.print_metrics();
|
||||
}
|
||||
});
|
||||
Some(handle)
|
||||
}
|
||||
|
||||
/// 更新处理次数
|
||||
pub fn add_process_count(&self, event_type: MetricsEventType) {
|
||||
if !self.config.enable_metrics {
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 Backoff 策略进行写入尝试
|
||||
let backoff = Backoff::new();
|
||||
loop {
|
||||
match self.metrics.write() {
|
||||
Ok(mut metrics) => {
|
||||
metrics.event_metrics[event_type.as_index()].process_count += 1;
|
||||
break;
|
||||
},
|
||||
Err(_) => {
|
||||
// 如果获取写锁失败,使用指数退避策略
|
||||
backoff.snooze();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// === 兼容性方法 ===
|
||||
|
||||
/// 兼容性构造函数
|
||||
pub fn new_with_metrics(
|
||||
_metrics: Arc<std::sync::RwLock<PerformanceMetrics>>,
|
||||
enable_metrics: bool,
|
||||
stream_name: String,
|
||||
) -> Self {
|
||||
Self::new(enable_metrics, stream_name)
|
||||
}
|
||||
|
||||
/// 获取完整的性能指标(兼容性方法)
|
||||
pub fn get_metrics(&self) -> PerformanceMetrics {
|
||||
PerformanceMetrics {
|
||||
uptime: self.get_uptime(),
|
||||
tx_metrics: self.get_event_metrics(EventType::Transaction),
|
||||
account_metrics: self.get_event_metrics(EventType::Account),
|
||||
block_meta_metrics: self.get_event_metrics(EventType::BlockMeta),
|
||||
processing_stats: self.get_processing_stats(),
|
||||
}
|
||||
}
|
||||
|
||||
// 保持向后兼容的方法
|
||||
/// 兼容性方法 - 添加交易处理计数
|
||||
#[inline]
|
||||
pub fn add_tx_process_count(&self) {
|
||||
self.add_process_count(MetricsEventType::Tx);
|
||||
self.record_process(EventType::Transaction);
|
||||
}
|
||||
|
||||
/// 兼容性方法 - 添加账户处理计数
|
||||
#[inline]
|
||||
pub fn add_account_process_count(&self) {
|
||||
self.add_process_count(MetricsEventType::Account);
|
||||
self.record_process(EventType::Account);
|
||||
}
|
||||
|
||||
/// 兼容性方法 - 添加区块元数据处理计数
|
||||
#[inline]
|
||||
pub fn add_block_meta_process_count(&self) {
|
||||
self.add_process_count(MetricsEventType::BlockMeta);
|
||||
self.record_process(EventType::BlockMeta);
|
||||
}
|
||||
|
||||
/// 更新性能指标
|
||||
/// 兼容性方法 - 更新指标
|
||||
#[inline]
|
||||
pub fn update_metrics(
|
||||
&self,
|
||||
event_type: MetricsEventType,
|
||||
events_processed: u64,
|
||||
processing_time_us: f64,
|
||||
signature: Option<Signature>,
|
||||
) {
|
||||
// 检查是否启用性能监控
|
||||
if !self.config.enable_metrics {
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 Backoff 策略进行写入尝试
|
||||
let backoff = Backoff::new();
|
||||
loop {
|
||||
match self.metrics.write() {
|
||||
Ok(mut metrics) => {
|
||||
let now = std::time::Instant::now();
|
||||
let index = event_type.as_index();
|
||||
|
||||
// 更新事件计数
|
||||
metrics.event_metrics[index].events_processed += events_processed;
|
||||
metrics.event_metrics[index].events_in_window += events_processed;
|
||||
|
||||
metrics.last_update_time = now;
|
||||
|
||||
// 更新处理时间统计
|
||||
if processing_time_us < metrics.min_processing_time_us
|
||||
|| metrics.min_processing_time_us == 0.0
|
||||
{
|
||||
metrics.min_processing_time_us = processing_time_us;
|
||||
}
|
||||
if processing_time_us > metrics.max_processing_time_us {
|
||||
metrics.max_processing_time_us = processing_time_us;
|
||||
}
|
||||
|
||||
// 计算平均处理时间 - 使用增量更新避免重复计算
|
||||
let total_events = metrics.event_metrics[index].events_processed;
|
||||
if total_events > 0 {
|
||||
let total_events_f64 = total_events as f64;
|
||||
let old_total = (total_events_f64 - events_processed as f64).max(0.0);
|
||||
|
||||
metrics.average_processing_time_us = if old_total > 0.0 {
|
||||
(metrics.average_processing_time_us * old_total
|
||||
+ processing_time_us * events_processed as f64)
|
||||
/ total_events_f64
|
||||
} else {
|
||||
processing_time_us
|
||||
};
|
||||
}
|
||||
|
||||
// 更新时间窗口指标
|
||||
let window_duration = std::time::Duration::from_secs(DEFAULT_METRICS_WINDOW_SECONDS);
|
||||
metrics.update_window_metrics(&event_type, now, window_duration);
|
||||
break;
|
||||
},
|
||||
Err(_) => {
|
||||
// 如果获取写锁失败,使用指数退避策略
|
||||
backoff.snooze();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 记录慢处理操作
|
||||
pub fn log_slow_processing(&self, processing_time_us: f64, event_count: usize) {
|
||||
if processing_time_us > SLOW_PROCESSING_THRESHOLD_US {
|
||||
log::warn!(
|
||||
"{} slow processing: {processing_time_us}us for {event_count} events",
|
||||
self.stream_name
|
||||
);
|
||||
}
|
||||
self.record_events(event_type, events_processed, processing_time_us);
|
||||
self.log_slow_processing(processing_time_us, events_processed as usize, signature);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,8 +556,9 @@ impl Clone for MetricsManager {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
metrics: self.metrics.clone(),
|
||||
config: self.config.clone(),
|
||||
enable_metrics: self.enable_metrics,
|
||||
stream_name: self.stream_name.clone(),
|
||||
background_task_running: AtomicBool::new(false), // 新实例不自动启动后台任务
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user