From a5dc8d66799412d3e19f6c80e4857ffac0269a5a Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Tue, 20 Feb 2024 02:25:35 -0500 Subject: [PATCH] feat: add queued pool truncate benchmarks (#6684) --- crates/transaction-pool/benches/truncate.rs | 80 +++++++++++++++------ crates/transaction-pool/src/pool/mod.rs | 2 +- crates/transaction-pool/src/pool/parked.rs | 2 +- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/crates/transaction-pool/benches/truncate.rs b/crates/transaction-pool/benches/truncate.rs index 63f433473..b5afed655 100644 --- a/crates/transaction-pool/benches/truncate.rs +++ b/crates/transaction-pool/benches/truncate.rs @@ -9,7 +9,7 @@ use proptest::{ }; use reth_primitives::{hex_literal::hex, Address}; use reth_transaction_pool::{ - pool::{BasefeeOrd, ParkedPool, PendingPool}, + pool::{BasefeeOrd, ParkedPool, PendingPool, QueuedOrd}, test_utils::{MockOrdering, MockTransaction, MockTransactionFactory}, SubPoolLimit, }; @@ -84,6 +84,23 @@ fn generate_many_transactions(senders: usize, max_depth: usize) -> Vec, senders: usize, max_depth: usize) { + println!("Generating transactions for benchmark with {senders} unique senders and a max depth of {max_depth}..."); + let txs = generate_many_transactions(senders, max_depth); + + // benchmark parked pool + truncate_basefee(group, "BasefeePool", txs.clone(), senders, max_depth); + + // benchmark pending pool + truncate_pending(group, "PendingPool", txs.clone(), senders, max_depth); + + // benchmark queued pool + truncate_queued(group, "QueuedPool", txs, senders, max_depth); + + // TODO: benchmark blob truncate +} + fn txpool_truncate(c: &mut Criterion) { let mut group = c.benchmark_group("Transaction Pool Truncate"); @@ -95,17 +112,8 @@ fn txpool_truncate(c: &mut Criterion) { for senders in [5, 10, 20, 100, 1000, 2000] { // the max we'll be benching is 20, because MAX_ACCOUNT_SLOTS so far is 16. So 20 should be // a reasonable worst-case benchmark - for max_depth in [5, 10, 20] { - println!("Generating transactions for benchmark with {senders} unique senders and a max depth of {max_depth}..."); - let txs = generate_many_transactions(senders, max_depth); - - // benchmark parked pool - truncate_parked(&mut group, "ParkedPool", txs.clone(), senders, max_depth); - - // benchmark pending pool - truncate_pending(&mut group, "PendingPool", txs, senders, max_depth); - - // TODO: benchmark blob truncate + for max_depth in [1, 5, 10, 20] { + benchmark_pools(&mut group, senders, max_depth); } } @@ -114,14 +122,12 @@ fn txpool_truncate(c: &mut Criterion) { // let's run a benchmark that includes a large number of senders and max_depth of 16 to ensure // we hit the TXPOOL_SUBPOOL_MAX_TXS_DEFAULT limit, which is currently 10k - println!("Generating transactions for large benchmark with {large_senders} unique senders and a max depth of {max_depth}..."); - let txs = generate_many_transactions(large_senders, max_depth); + benchmark_pools(&mut group, large_senders, max_depth); - // benchmark parked - truncate_parked(&mut group, "ParkedPool", txs.clone(), large_senders, max_depth); - - // benchmark pending - truncate_pending(&mut group, "PendingPool", txs, large_senders, max_depth); + // now we'll run a more realistic benchmark, with max depth of 1 and 15000 senders + let realistic_senders = 15000; + let realistic_max_depth = 1; + benchmark_pools(&mut group, realistic_senders, realistic_max_depth); } fn truncate_pending( @@ -159,7 +165,41 @@ fn truncate_pending( }); } -fn truncate_parked( +fn truncate_queued( + group: &mut BenchmarkGroup<'_, WallTime>, + description: &str, + seed: Vec, + senders: usize, + max_depth: usize, +) { + let setup = || { + let mut txpool = ParkedPool::>::default(); + let mut f = MockTransactionFactory::default(); + + for tx in seed.iter() { + txpool.add_transaction(f.validated_arc(tx.clone())); + } + txpool + }; + + let group_id = format!( + "txpool | total txs: {} | total senders: {} | max depth: {} | {}", + seed.len(), + senders, + max_depth, + description, + ); + + // for now we just use the default SubPoolLimit + group.bench_function(group_id, |b| { + b.iter_with_setup(setup, |mut txpool| { + txpool.truncate_pool(SubPoolLimit::default()); + std::hint::black_box(()); + }); + }); +} + +fn truncate_basefee( group: &mut BenchmarkGroup<'_, WallTime>, description: &str, seed: Vec, diff --git a/crates/transaction-pool/src/pool/mod.rs b/crates/transaction-pool/src/pool/mod.rs index 0ed073477..62b9d2cec 100644 --- a/crates/transaction-pool/src/pool/mod.rs +++ b/crates/transaction-pool/src/pool/mod.rs @@ -108,7 +108,7 @@ pub use best::BestTransactionFilter; pub use blob::{blob_tx_priority, fee_delta}; pub use events::{FullTransactionEvent, TransactionEvent}; pub use listener::{AllTransactionsEvents, TransactionEvents}; -pub use parked::{BasefeeOrd, ParkedOrd, ParkedPool}; +pub use parked::{BasefeeOrd, ParkedOrd, ParkedPool, QueuedOrd}; pub use pending::PendingPool; mod best; diff --git a/crates/transaction-pool/src/pool/parked.rs b/crates/transaction-pool/src/pool/parked.rs index 3b534431b..5131620dc 100644 --- a/crates/transaction-pool/src/pool/parked.rs +++ b/crates/transaction-pool/src/pool/parked.rs @@ -442,7 +442,7 @@ impl Ord for BasefeeOrd { /// The primary order function always compares the transaction costs first. In case these /// are equal, it compares the timestamps when the transactions were created. #[derive(Debug)] -pub(crate) struct QueuedOrd(Arc>); +pub struct QueuedOrd(Arc>); impl_ord_wrapper!(QueuedOrd);