perf: optimize txpool_status RPC by avoiding full transaction collection (#17392)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Acat
2025-07-14 22:07:32 +08:00
committed by GitHub
parent b9c63f6a10
commit 44cc67be00
7 changed files with 29 additions and 4 deletions

View File

@@ -88,8 +88,8 @@ where
/// Handler for `txpool_status`
async fn txpool_status(&self) -> RpcResult<TxpoolStatus> {
trace!(target: "rpc::eth", "Serving txpool_status");
let all = self.pool.all_transactions();
Ok(TxpoolStatus { pending: all.pending.len() as u64, queued: all.queued.len() as u64 })
let (pending, queued) = self.pool.pending_and_queued_txn_count();
Ok(TxpoolStatus { pending: pending as u64, queued: queued as u64 })
}
/// Returns a summary of all the transactions currently pending for inclusion in the next

View File

@@ -591,6 +591,13 @@ where
self.pool.queued_transactions()
}
fn pending_and_queued_txn_count(&self) -> (usize, usize) {
let data = self.pool.get_pool_data();
let pending = data.pending_transactions_count();
let queued = data.queued_transactions_count();
(pending, queued)
}
fn all_transactions(&self) -> AllPoolTransactions<Self::Transaction> {
self.pool.all_transactions()
}

View File

@@ -190,6 +190,10 @@ impl<T: EthPoolTransaction> TransactionPool for NoopTransactionPool<T> {
vec![]
}
fn pending_and_queued_txn_count(&self) -> (usize, usize) {
(0, 0)
}
fn all_transactions(&self) -> AllPoolTransactions<Self::Transaction> {
AllPoolTransactions::default()
}

View File

@@ -131,7 +131,7 @@ impl<T: ParkedOrd> ParkedPool<T> {
/// Returns an iterator over all transactions in the pool
pub(crate) fn all(
&self,
) -> impl Iterator<Item = Arc<ValidPoolTransaction<T::Transaction>>> + '_ {
) -> impl ExactSizeIterator<Item = Arc<ValidPoolTransaction<T::Transaction>>> + '_ {
self.by_id.values().map(|tx| tx.transaction.clone().into())
}

View File

@@ -158,7 +158,7 @@ impl<T: TransactionOrdering> PendingPool<T> {
/// Returns an iterator over all transactions in the pool
pub(crate) fn all(
&self,
) -> impl Iterator<Item = Arc<ValidPoolTransaction<T::Transaction>>> + '_ {
) -> impl ExactSizeIterator<Item = Arc<ValidPoolTransaction<T::Transaction>>> + '_ {
self.by_id.values().map(|tx| tx.transaction.clone())
}

View File

@@ -434,6 +434,11 @@ impl<T: TransactionOrdering> TxPool<T> {
self.pending_pool.all()
}
/// Returns the number of transactions from the pending sub-pool
pub(crate) fn pending_transactions_count(&self) -> usize {
self.pending_pool.len()
}
/// Returns all pending transactions filtered by predicate
pub(crate) fn pending_transactions_with_predicate(
&self,
@@ -462,6 +467,11 @@ impl<T: TransactionOrdering> TxPool<T> {
self.basefee_pool.all().chain(self.queued_pool.all())
}
/// Returns the number of transactions in parked pools
pub(crate) fn queued_transactions_count(&self) -> usize {
self.basefee_pool.len() + self.queued_pool.len()
}
/// Returns queued and pending transactions for the specified sender
pub fn queued_and_pending_txs_by_sender(
&self,

View File

@@ -355,6 +355,10 @@ pub trait TransactionPool: Clone + Debug + Send + Sync {
/// Consumer: RPC
fn queued_transactions(&self) -> Vec<Arc<ValidPoolTransaction<Self::Transaction>>>;
/// Returns the number of transactions that are ready for inclusion in the next block and the
/// number of transactions that are ready for inclusion in future blocks: `(pending, queued)`.
fn pending_and_queued_txn_count(&self) -> (usize, usize);
/// Returns all transactions that are currently in the pool grouped by whether they are ready
/// for inclusion in the next block or not.
///