Files
solana-streamer/src/streaming/grpc/pool.rs
T

528 lines
16 KiB
Rust

use super::types::{AccountPretty, BlockMetaPretty, TransactionPretty};
use crate::streaming::event_parser::common::high_performance_clock::get_high_perf_clock;
use solana_sdk::{pubkey::Pubkey, signature::Signature};
use std::collections::VecDeque;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use yellowstone_grpc_proto::{
geyser::{SubscribeUpdateAccount, SubscribeUpdateBlockMeta, SubscribeUpdateTransaction},
prost_types::Timestamp,
};
/// 通用对象池特征
pub trait ObjectPool<T> {
fn acquire(&self) -> PooledObject<T>;
fn return_object(&self, obj: Box<T>);
}
/// 带自动归还的智能指针
pub struct PooledObject<T> {
object: Option<Box<T>>,
pool: Arc<Mutex<VecDeque<Box<T>>>>,
max_size: usize,
}
impl<T> PooledObject<T> {
#[allow(dead_code)]
fn new(object: Box<T>, pool: Arc<Mutex<VecDeque<Box<T>>>>, max_size: usize) -> Self {
Self { object: Some(object), pool, max_size }
}
}
impl<T> Drop for PooledObject<T> {
fn drop(&mut self) {
if let Some(obj) = self.object.take() {
let mut pool = self.pool.lock().unwrap();
if pool.len() < self.max_size {
pool.push_back(obj);
}
// 超过最大容量时直接丢弃
}
}
}
impl<T> std::ops::Deref for PooledObject<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.object.as_ref().unwrap()
}
}
impl<T> std::ops::DerefMut for PooledObject<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.object.as_mut().unwrap()
}
}
/// AccountPretty 对象池
pub struct AccountPrettyPool {
pool: Arc<Mutex<VecDeque<Box<AccountPretty>>>>,
max_size: usize,
}
impl AccountPrettyPool {
pub fn new(initial_size: usize, max_size: usize) -> Self {
let mut pool = VecDeque::with_capacity(initial_size);
// 预分配对象
for _ in 0..initial_size {
pool.push_back(Box::new(AccountPretty::default()));
}
Self { pool: Arc::new(Mutex::new(pool)), max_size }
}
pub fn acquire(&self) -> PooledAccountPretty {
let mut pool = self.pool.lock().unwrap();
let account = match pool.pop_front() {
Some(reused) => reused,
None => Box::new(AccountPretty::default()),
};
PooledAccountPretty { account, pool: Arc::clone(&self.pool), max_size: self.max_size }
}
}
/// 带自动归还的 AccountPretty
pub struct PooledAccountPretty {
account: Box<AccountPretty>,
pool: Arc<Mutex<VecDeque<Box<AccountPretty>>>>,
max_size: usize,
}
impl PooledAccountPretty {
/// 从 gRPC 更新重置数据
pub fn reset_from_update(&mut self, account_update: SubscribeUpdateAccount) -> bool {
let Some(account_info) = account_update.account else {
log::debug!("drop account update without account payload");
return false;
};
self.account.slot = account_update.slot;
self.account.signature = if let Some(txn_signature) = account_info.txn_signature {
if txn_signature.len() != 64 {
log::debug!("drop account update with invalid signature length");
return false;
}
match Signature::try_from(txn_signature.as_slice()) {
Ok(sig) => sig,
Err(_) => {
log::debug!("drop account update with invalid transaction signature");
return false;
}
}
} else {
Signature::default()
};
if account_info.pubkey.len() != 32 {
log::debug!("drop account update with invalid account pubkey length");
return false;
}
self.account.pubkey = match Pubkey::try_from(account_info.pubkey.as_slice()) {
Ok(pubkey) => pubkey,
Err(_) => {
log::debug!("drop account update with invalid account pubkey");
return false;
}
};
self.account.executable = account_info.executable;
self.account.lamports = account_info.lamports;
if account_info.owner.len() != 32 {
log::debug!("drop account update with invalid owner pubkey length");
return false;
}
self.account.owner = match Pubkey::try_from(account_info.owner.as_slice()) {
Ok(owner) => owner,
Err(_) => {
log::debug!("drop account update with invalid owner pubkey");
return false;
}
};
self.account.rent_epoch = account_info.rent_epoch;
// 优化数据字段的重用
let new_data = account_info.data;
if self.account.data.capacity() >= new_data.len() {
self.account.data.clear();
self.account.data.extend_from_slice(&new_data);
} else {
self.account.data = new_data;
}
self.account.recv_us = get_high_perf_clock();
true
}
}
impl Drop for PooledAccountPretty {
fn drop(&mut self) {
let mut pool = self.pool.lock().unwrap();
if pool.len() < self.max_size {
// 清理敏感数据
self.account.data.clear();
self.account.signature = Signature::default();
self.account.pubkey = Pubkey::default();
self.account.owner = Pubkey::default();
pool.push_back(std::mem::take(&mut self.account));
}
}
}
impl std::ops::Deref for PooledAccountPretty {
type Target = AccountPretty;
fn deref(&self) -> &Self::Target {
&self.account
}
}
impl std::ops::DerefMut for PooledAccountPretty {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.account
}
}
/// BlockMetaPretty 对象池
pub struct BlockMetaPrettyPool {
pool: Arc<Mutex<VecDeque<Box<BlockMetaPretty>>>>,
max_size: usize,
}
impl BlockMetaPrettyPool {
pub fn new(initial_size: usize, max_size: usize) -> Self {
let mut pool = VecDeque::with_capacity(initial_size);
// 预分配对象
for _ in 0..initial_size {
pool.push_back(Box::new(BlockMetaPretty::default()));
}
Self { pool: Arc::new(Mutex::new(pool)), max_size }
}
pub fn acquire(&self) -> PooledBlockMetaPretty {
let mut pool = self.pool.lock().unwrap();
let block_meta = match pool.pop_front() {
Some(reused) => reused,
None => Box::new(BlockMetaPretty::default()),
};
PooledBlockMetaPretty { block_meta, pool: Arc::clone(&self.pool), max_size: self.max_size }
}
}
/// 带自动归还的 BlockMetaPretty
pub struct PooledBlockMetaPretty {
block_meta: Box<BlockMetaPretty>,
pool: Arc<Mutex<VecDeque<Box<BlockMetaPretty>>>>,
max_size: usize,
}
impl PooledBlockMetaPretty {
/// 从 gRPC 更新重置数据
pub fn reset_from_update(
&mut self,
block_update: SubscribeUpdateBlockMeta,
block_time: Option<Timestamp>,
) {
self.block_meta.slot = block_update.slot;
self.block_meta.block_hash = block_update.blockhash;
self.block_meta.block_time = block_time;
self.block_meta.recv_us = get_high_perf_clock();
}
}
impl Drop for PooledBlockMetaPretty {
fn drop(&mut self) {
let mut pool = self.pool.lock().unwrap();
if pool.len() < self.max_size {
// 清理数据
self.block_meta.block_hash.clear();
self.block_meta.block_time = None;
pool.push_back(std::mem::take(&mut self.block_meta));
}
}
}
impl std::ops::Deref for PooledBlockMetaPretty {
type Target = BlockMetaPretty;
fn deref(&self) -> &Self::Target {
&self.block_meta
}
}
impl std::ops::DerefMut for PooledBlockMetaPretty {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.block_meta
}
}
/// TransactionPretty 对象池
pub struct TransactionPrettyPool {
pool: Arc<Mutex<VecDeque<Box<TransactionPretty>>>>,
max_size: usize,
}
impl TransactionPrettyPool {
pub fn new(initial_size: usize, max_size: usize) -> Self {
let mut pool = VecDeque::with_capacity(initial_size);
// 预分配对象
for _ in 0..initial_size {
pool.push_back(Box::new(TransactionPretty::default()));
}
Self { pool: Arc::new(Mutex::new(pool)), max_size }
}
pub fn acquire(&self) -> PooledTransactionPretty {
let mut pool = self.pool.lock().unwrap();
let transaction = match pool.pop_front() {
Some(reused) => reused,
None => Box::new(TransactionPretty::default()),
};
PooledTransactionPretty {
transaction,
pool: Arc::clone(&self.pool),
max_size: self.max_size,
}
}
}
/// 带自动归还的 TransactionPretty
pub struct PooledTransactionPretty {
transaction: Box<TransactionPretty>,
pool: Arc<Mutex<VecDeque<Box<TransactionPretty>>>>,
max_size: usize,
}
impl PooledTransactionPretty {
/// 从 gRPC 更新重置数据
pub fn reset_from_update(
&mut self,
tx_update: SubscribeUpdateTransaction,
block_time: Option<Timestamp>,
) -> bool {
let Some(tx) = tx_update.transaction else {
log::debug!("drop transaction update without transaction payload");
return false;
};
if tx.signature.len() != 64 {
log::debug!("drop transaction update with invalid signature length");
return false;
}
self.transaction.slot = tx_update.slot;
self.transaction.tx_index = Some(tx.index);
self.transaction.block_time = block_time;
self.transaction.block_hash.clear(); // 重置 block_hash
self.transaction.signature = match Signature::try_from(tx.signature.as_slice()) {
Ok(signature) => signature,
Err(_) => {
log::debug!("drop transaction update with invalid signature");
return false;
}
};
self.transaction.is_vote = tx.is_vote;
self.transaction.recv_us = get_high_perf_clock();
self.transaction.grpc_tx = tx;
true
}
}
impl Drop for PooledTransactionPretty {
fn drop(&mut self) {
let mut pool = self.pool.lock().unwrap();
if pool.len() < self.max_size {
// 清理数据
self.transaction.block_hash.clear();
self.transaction.block_time = None;
self.transaction.signature = Signature::default();
pool.push_back(std::mem::take(&mut self.transaction));
}
}
}
impl std::ops::Deref for PooledTransactionPretty {
type Target = TransactionPretty;
fn deref(&self) -> &Self::Target {
&self.transaction
}
}
impl std::ops::DerefMut for PooledTransactionPretty {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.transaction
}
}
/// EventPretty 对象池(组合池)
pub struct EventPrettyPool {
account_pool: AccountPrettyPool,
block_pool: BlockMetaPrettyPool,
transaction_pool: TransactionPrettyPool,
}
impl EventPrettyPool {
pub fn new() -> Self {
Self {
account_pool: AccountPrettyPool::new(10000, 20000),
block_pool: BlockMetaPrettyPool::new(500, 1000),
transaction_pool: TransactionPrettyPool::new(10000, 20000),
}
}
/// 获取账户事件对象
pub fn acquire_account(&self) -> PooledAccountPretty {
self.account_pool.acquire()
}
/// 获取区块事件对象
pub fn acquire_block(&self) -> PooledBlockMetaPretty {
self.block_pool.acquire()
}
/// 获取交易事件对象
pub fn acquire_transaction(&self) -> PooledTransactionPretty {
self.transaction_pool.acquire()
}
}
impl Default for EventPrettyPool {
fn default() -> Self {
Self::new()
}
}
/// 对象池管理器(单例)
pub struct PoolManager {
event_pool: EventPrettyPool,
}
impl PoolManager {
pub fn new() -> Self {
Self { event_pool: EventPrettyPool::new() }
}
pub fn get_event_pool(&self) -> &EventPrettyPool {
&self.event_pool
}
}
impl Default for PoolManager {
fn default() -> Self {
Self::new()
}
}
/// 工厂函数用于创建优化的 EventPretty
impl EventPrettyPool {
/// 创建账户事件 - 使用对象池优化
pub fn try_create_account_event_optimized(
&self,
update: SubscribeUpdateAccount,
) -> Option<AccountPretty> {
let mut pooled_account = self.acquire_account();
if !pooled_account.reset_from_update(update) {
return None;
}
// 移动数据而不是克隆,避免多余的内存分配
let result = std::mem::take(pooled_account.deref_mut());
Some(result)
}
/// 创建账户事件 - 使用对象池优化
pub fn create_account_event_optimized(&self, update: SubscribeUpdateAccount) -> AccountPretty {
self.try_create_account_event_optimized(update).unwrap_or_default()
}
/// 创建区块事件 - 使用对象池优化
pub fn create_block_event_optimized(
&self,
update: SubscribeUpdateBlockMeta,
block_time: Option<Timestamp>,
) -> BlockMetaPretty {
let mut pooled_block = self.acquire_block();
pooled_block.reset_from_update(update, block_time);
// 移动数据而不是克隆
let result = std::mem::take(pooled_block.deref_mut());
result
}
/// 创建交易事件 - 使用对象池优化
pub fn try_create_transaction_event_optimized(
&self,
update: SubscribeUpdateTransaction,
block_time: Option<Timestamp>,
) -> Option<TransactionPretty> {
let mut pooled_tx = self.acquire_transaction();
if !pooled_tx.reset_from_update(update, block_time) {
return None;
}
// 移动数据而不是克隆
let result = std::mem::take(pooled_tx.deref_mut());
Some(result)
}
/// 创建交易事件 - 使用对象池优化
pub fn create_transaction_event_optimized(
&self,
update: SubscribeUpdateTransaction,
block_time: Option<Timestamp>,
) -> TransactionPretty {
self.try_create_transaction_event_optimized(update, block_time).unwrap_or_default()
}
}
// 全局池管理器实例
pub static GLOBAL_POOL_MANAGER: std::sync::LazyLock<PoolManager> =
std::sync::LazyLock::new(PoolManager::new);
/// 便捷的全局工厂函数
pub mod factory {
use super::*;
/// 尝试使用对象池创建账户事件,坏 gRPC update 返回 None
pub fn try_create_account_pretty_pooled(
update: SubscribeUpdateAccount,
) -> Option<AccountPretty> {
GLOBAL_POOL_MANAGER.get_event_pool().try_create_account_event_optimized(update)
}
/// 使用对象池创建账户事件(推荐用于高性能场景)
pub fn create_account_pretty_pooled(update: SubscribeUpdateAccount) -> AccountPretty {
GLOBAL_POOL_MANAGER.get_event_pool().create_account_event_optimized(update)
}
/// 使用对象池创建区块事件(推荐用于高性能场景)
pub fn create_block_meta_pretty_pooled(
update: SubscribeUpdateBlockMeta,
block_time: Option<Timestamp>,
) -> BlockMetaPretty {
GLOBAL_POOL_MANAGER.get_event_pool().create_block_event_optimized(update, block_time)
}
/// 尝试使用对象池创建交易事件,坏 gRPC update 返回 None
pub fn try_create_transaction_pretty_pooled(
update: SubscribeUpdateTransaction,
block_time: Option<Timestamp>,
) -> Option<TransactionPretty> {
GLOBAL_POOL_MANAGER
.get_event_pool()
.try_create_transaction_event_optimized(update, block_time)
}
/// 使用对象池创建交易事件(推荐用于高性能场景)
pub fn create_transaction_pretty_pooled(
update: SubscribeUpdateTransaction,
block_time: Option<Timestamp>,
) -> TransactionPretty {
GLOBAL_POOL_MANAGER.get_event_pool().create_transaction_event_optimized(update, block_time)
}
}