perf: Major event processing system refactor for improved performance

This commit is contained in:
ysq
2025-08-28 14:49:56 +08:00
parent 9ea4dab4df
commit 218abd3aa4
19 changed files with 292 additions and 574 deletions
+97
View File
@@ -0,0 +1,97 @@
/// Macro to generate boilerplate EventParser implementation for protocol parsers
///
/// This macro eliminates the repetitive code where each parser simply delegates
/// all EventParser trait methods to its inner GenericEventParser.
///
/// Usage:
/// ```rust
/// impl_event_parser_delegate!(MyEventParser);
/// ```
///
/// This will generate the complete EventParser implementation that delegates
/// all methods to `self.inner`.
#[macro_export]
macro_rules! impl_event_parser_delegate {
($parser_type:ty) => {
#[async_trait::async_trait]
impl $crate::streaming::event_parser::core::traits::EventParser for $parser_type {
fn inner_instruction_configs(
&self,
) -> std::collections::HashMap<
Vec<u8>,
Vec<$crate::streaming::event_parser::core::traits::GenericEventParseConfig>,
> {
self.inner.inner_instruction_configs()
}
fn instruction_configs(
&self,
) -> std::collections::HashMap<
Vec<u8>,
Vec<$crate::streaming::event_parser::core::traits::GenericEventParseConfig>,
> {
self.inner.instruction_configs()
}
fn parse_events_from_inner_instruction(
&self,
inner_instruction: &solana_sdk::instruction::CompiledInstruction,
signature: solana_sdk::signature::Signature,
slot: u64,
block_time: Option<prost_types::Timestamp>,
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<solana_sdk::pubkey::Pubkey>,
transaction_index: Option<u64>,
) -> Vec<Box<dyn $crate::streaming::event_parser::core::traits::UnifiedEvent>> {
self.inner.parse_events_from_inner_instruction(
inner_instruction,
signature,
slot,
block_time,
program_received_time_us,
outer_index,
inner_index,
bot_wallet,
transaction_index,
)
}
fn parse_events_from_instruction(
&self,
instruction: &solana_sdk::instruction::CompiledInstruction,
accounts: &[solana_sdk::pubkey::Pubkey],
signature: solana_sdk::signature::Signature,
slot: u64,
block_time: Option<prost_types::Timestamp>,
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<solana_sdk::pubkey::Pubkey>,
transaction_index: Option<u64>,
) -> Vec<Box<dyn $crate::streaming::event_parser::core::traits::UnifiedEvent>> {
self.inner.parse_events_from_instruction(
instruction,
accounts,
signature,
slot,
block_time,
program_received_time_us,
outer_index,
inner_index,
bot_wallet,
transaction_index,
)
}
fn should_handle(&self, program_id: &solana_sdk::pubkey::Pubkey) -> bool {
self.inner.should_handle(program_id)
}
fn supported_program_ids(&self) -> Vec<solana_sdk::pubkey::Pubkey> {
self.inner.supported_program_ids()
}
}
};
}
+1
View File
@@ -1,4 +1,5 @@
pub mod common_event_parser;
pub mod traits;
pub mod account_event_parser;
pub mod macros;
pub use traits::{EventParser, UnifiedEvent};
+49 -17
View File
@@ -68,16 +68,13 @@ pub trait UnifiedEvent: Debug + Send + Sync {
/// Get transaction index in slot
fn transaction_index(&self) -> Option<u64>;
/// Set transaction index in slot
fn set_transaction_index(&mut self, transaction_index: Option<u64>);
}
/// 事件解析器trait - 定义了事件解析的核心方法
#[async_trait::async_trait]
pub trait EventParser: Send + Sync {
/// 获取内联指令解析配置
fn inner_instruction_configs(&self) -> HashMap<&'static str, Vec<GenericEventParseConfig>>;
fn inner_instruction_configs(&self) -> HashMap<Vec<u8>, Vec<GenericEventParseConfig>>;
/// 获取指令解析配置
fn instruction_configs(&self) -> HashMap<Vec<u8>, Vec<GenericEventParseConfig>>;
/// 从内联指令中解析事件数据
@@ -91,6 +88,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Vec<Box<dyn UnifiedEvent>>;
/// 从指令中解析事件数据
@@ -105,6 +104,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Vec<Box<dyn UnifiedEvent>>;
/// 从VersionedTransaction中解析指令事件的通用方法
@@ -118,6 +119,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us: i64,
accounts: &[Pubkey],
inner_instructions: &[InnerInstructions],
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Result<Vec<Box<dyn UnifiedEvent>>> {
// 预分配容量,避免动态扩容
let mut instruction_events = Vec::with_capacity(16);
@@ -149,6 +152,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us,
index as i64,
None,
bot_wallet,
Some(index as u64),
)
.await
{
@@ -188,6 +193,7 @@ pub trait EventParser: Send + Sync {
block_time: Option<Timestamp>,
program_received_time_us: i64,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Result<Vec<Box<dyn UnifiedEvent>>> {
let accounts: Vec<Pubkey> = versioned_tx.message.static_account_keys().to_vec();
let events = self
@@ -199,6 +205,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us,
&accounts,
&[],
bot_wallet,
transaction_index,
)
.await
.unwrap_or_else(|_e| vec![]);
@@ -213,6 +221,7 @@ pub trait EventParser: Send + Sync {
block_time: Option<Timestamp>,
program_received_time_us: i64,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Result<Vec<Box<dyn UnifiedEvent>>> {
let versioned_tx = tx.get_transaction();
let meta = tx.get_status_meta();
@@ -254,6 +263,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us,
&accounts_for_task1,
&inner_instructions_for_task1,
bot_wallet,
transaction_index,
)
.await
.unwrap_or_else(|_e| vec![])
@@ -305,6 +316,8 @@ pub trait EventParser: Send + Sync {
*program_received_time_us,
*outer_index,
*inner_index,
bot_wallet,
transaction_index,
)
.await
{
@@ -348,6 +361,8 @@ pub trait EventParser: Send + Sync {
*program_received_time_us,
*outer_index,
*inner_index,
bot_wallet,
transaction_index,
)
.await
{
@@ -496,6 +511,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Result<Vec<Box<dyn UnifiedEvent>>> {
let slot = slot.unwrap_or(0);
let events = self.parse_events_from_inner_instruction(
@@ -506,6 +523,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us,
outer_index,
inner_index,
bot_wallet,
transaction_index,
);
Ok(events)
}
@@ -521,6 +540,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Result<Vec<Box<dyn UnifiedEvent>>> {
let slot = slot.unwrap_or(0);
let events = self.parse_events_from_instruction(
@@ -532,6 +553,8 @@ pub trait EventParser: Send + Sync {
program_received_time_us,
outer_index,
inner_index,
bot_wallet,
transaction_index,
);
Ok(events)
}
@@ -555,7 +578,7 @@ impl Clone for Box<dyn UnifiedEvent> {
pub struct GenericEventParseConfig {
pub program_id: Pubkey,
pub protocol_type: ProtocolType,
pub inner_instruction_discriminator: &'static str,
pub inner_instruction_discriminator: &'static [u8],
pub instruction_discriminator: &'static [u8],
pub event_type: EventType,
pub inner_instruction_parser: Option<InnerInstructionEventParser>,
@@ -573,7 +596,7 @@ pub type InstructionEventParser =
/// 通用事件解析器基类
pub struct GenericEventParser {
pub program_ids: Vec<Pubkey>,
pub inner_instruction_configs: HashMap<&'static str, Vec<GenericEventParseConfig>>,
pub inner_instruction_configs: HashMap<Vec<u8>, Vec<GenericEventParseConfig>>,
pub instruction_configs: HashMap<Vec<u8>, Vec<GenericEventParseConfig>>,
}
@@ -585,10 +608,12 @@ impl GenericEventParser {
let mut instruction_configs = HashMap::with_capacity(configs.len());
for config in configs {
inner_instruction_configs
.entry(config.inner_instruction_discriminator)
.or_insert_with(Vec::new)
.push(config.clone());
if config.inner_instruction_discriminator.len() > 0 {
inner_instruction_configs
.entry(config.inner_instruction_discriminator.to_vec())
.or_insert_with(Vec::new)
.push(config.clone());
}
instruction_configs
.entry(config.instruction_discriminator.to_vec())
.or_insert_with(Vec::new)
@@ -610,6 +635,7 @@ impl GenericEventParser {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
transaction_index: Option<u64>,
) -> Option<Box<dyn UnifiedEvent>> {
if let Some(parser) = config.inner_instruction_parser {
let timestamp = block_time.unwrap_or(Timestamp { seconds: 0, nanos: 0 });
@@ -626,6 +652,7 @@ impl GenericEventParser {
outer_index,
inner_index,
program_received_time_us,
transaction_index,
);
parser(data, metadata)
} else {
@@ -646,6 +673,7 @@ impl GenericEventParser {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
transaction_index: Option<u64>,
) -> Option<Box<dyn UnifiedEvent>> {
if let Some(parser) = config.instruction_parser {
let timestamp = block_time.unwrap_or(Timestamp { seconds: 0, nanos: 0 });
@@ -662,6 +690,7 @@ impl GenericEventParser {
outer_index,
inner_index,
program_received_time_us,
transaction_index,
);
parser(data, account_pubkeys, metadata)
} else {
@@ -672,7 +701,7 @@ impl GenericEventParser {
#[async_trait::async_trait]
impl EventParser for GenericEventParser {
fn inner_instruction_configs(&self) -> HashMap<&'static str, Vec<GenericEventParseConfig>> {
fn inner_instruction_configs(&self) -> HashMap<Vec<u8>, Vec<GenericEventParseConfig>> {
// 返回引用而非克隆,减少内存分配
self.inner_instruction_configs.clone()
}
@@ -691,17 +720,16 @@ impl EventParser for GenericEventParser {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Vec<Box<dyn UnifiedEvent>> {
let inner_instruction_data_decoded = inner_instruction.data.clone();
if inner_instruction_data_decoded.len() < 16 {
if inner_instruction.data.len() < 16 {
return Vec::new();
}
let inner_instruction_data_decoded_str =
format!("0x{}", hex::encode(&inner_instruction_data_decoded));
let data = &inner_instruction_data_decoded[16..];
let data = &inner_instruction.data[16..];
let mut events = Vec::new();
for (disc, configs) in &self.inner_instruction_configs {
if discriminator_matches(&inner_instruction_data_decoded_str, disc) {
if data == disc {
for config in configs {
if let Some(event) = self.parse_inner_instruction_event(
config,
@@ -712,6 +740,7 @@ impl EventParser for GenericEventParser {
program_received_time_us,
outer_index,
inner_index,
transaction_index,
) {
events.push(event);
}
@@ -733,6 +762,8 @@ impl EventParser for GenericEventParser {
program_received_time_us: i64,
outer_index: i64,
inner_index: Option<i64>,
bot_wallet: Option<Pubkey>,
transaction_index: Option<u64>,
) -> Vec<Box<dyn UnifiedEvent>> {
let program_id = accounts[instruction.program_id_index as usize];
if !self.should_handle(&program_id) {
@@ -767,6 +798,7 @@ impl EventParser for GenericEventParser {
program_received_time_us,
outer_index,
inner_index,
transaction_index,
) {
events.push(event);
}