Skip to content

Commit cb1a47c

Browse files
committed
feat: optimize mempool iteration by skipping repeated invocation after mempool exhausted
1 parent 70bef50 commit cb1a47c

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

stackslib/src/chainstate/stacks/miner.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2228,10 +2228,10 @@ impl StacksBlockBuilder {
22282228

22292229
debug!("Block transaction selection begins (parent height = {tip_height})");
22302230
let result = {
2231-
let mut intermediate_result: Result<_, Error> = Ok(0);
2231+
let mut loop_result = Ok(());
22322232
while block_limit_hit != BlockLimitFunction::LIMIT_REACHED {
22332233
let mut num_considered = 0;
2234-
intermediate_result = mempool.iterate_candidates(
2234+
let intermediate_result = mempool.iterate_candidates(
22352235
epoch_tx,
22362236
&mut tx_events,
22372237
mempool_settings.clone(),
@@ -2390,16 +2390,27 @@ impl StacksBlockBuilder {
23902390
let _ = mempool.drop_and_blacklist_txs(&to_drop_and_blacklist);
23912391
}
23922392

2393-
if intermediate_result.is_err() {
2394-
break;
2393+
match intermediate_result {
2394+
Err(e) => {
2395+
loop_result = Err(e);
2396+
break;
2397+
}
2398+
Ok((_txs_considered, stop_reason)) => {
2399+
match stop_reason {
2400+
MempoolIterationStopReason::NoMoreCandidates => break,
2401+
MempoolIterationStopReason::DeadlineReached => break,
2402+
// if the iterator function exited, let the loop tick: it checks the block limits
2403+
MempoolIterationStopReason::IteratorExited => {}
2404+
}
2405+
}
23952406
}
23962407

23972408
if num_considered == 0 {
23982409
break;
23992410
}
24002411
}
24012412
debug!("Block transaction selection finished (parent height {}): {} transactions selected ({} considered)", &tip_height, num_txs, considered.len());
2402-
intermediate_result
2413+
loop_result
24032414
};
24042415

24052416
mempool.drop_txs(&invalidated_txs)?;

stackslib/src/chainstate/stacks/tests/block_construction.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5072,6 +5072,7 @@ fn paramaterized_mempool_walk_test(
50725072
},
50735073
)
50745074
.unwrap()
5075+
.0
50755076
== 0
50765077
{
50775078
break;

stackslib/src/core/mempool.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ pub enum MemPoolSyncData {
144144
TxTags([u8; 32], Vec<TxTag>),
145145
}
146146

147+
pub enum MempoolIterationStopReason {
148+
NoMoreCandidates,
149+
DeadlineReached,
150+
/// If the iteration function supplied to mempool iteration exited
151+
/// (i.e., the transaction evaluator returned an early exit command)
152+
IteratorExited,
153+
}
154+
147155
impl StacksMessageCodec for MemPoolSyncData {
148156
fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), codec_error> {
149157
match *self {
@@ -1592,7 +1600,7 @@ impl MemPoolDB {
15921600
output_events: &mut Vec<TransactionEvent>,
15931601
settings: MemPoolWalkSettings,
15941602
mut todo: F,
1595-
) -> Result<u64, E>
1603+
) -> Result<(u64, MempoolIterationStopReason), E>
15961604
where
15971605
C: ClarityConnection,
15981606
F: FnMut(
@@ -1643,11 +1651,11 @@ impl MemPoolDB {
16431651
.query(NO_PARAMS)
16441652
.map_err(|err| Error::SqliteError(err))?;
16451653

1646-
loop {
1654+
let stop_reason = loop {
16471655
if start_time.elapsed().as_millis() > settings.max_walk_time_ms as u128 {
16481656
debug!("Mempool iteration deadline exceeded";
16491657
"deadline_ms" => settings.max_walk_time_ms);
1650-
break;
1658+
break MempoolIterationStopReason::DeadlineReached;
16511659
}
16521660

16531661
let start_with_no_estimate =
@@ -1687,7 +1695,7 @@ impl MemPoolDB {
16871695
),
16881696
None => {
16891697
debug!("No more transactions to consider in mempool");
1690-
break;
1698+
break MempoolIterationStopReason::NoMoreCandidates;
16911699
}
16921700
}
16931701
}
@@ -1875,7 +1883,7 @@ impl MemPoolDB {
18751883
}
18761884
None => {
18771885
debug!("Mempool iteration early exit from iterator");
1878-
break;
1886+
break MempoolIterationStopReason::IteratorExited;
18791887
}
18801888
}
18811889

@@ -1885,7 +1893,7 @@ impl MemPoolDB {
18851893
candidate_cache.len()
18861894
);
18871895
candidate_cache.reset();
1888-
}
1896+
};
18891897

18901898
// drop these rusqlite statements and queries, since their existence as immutable borrows on the
18911899
// connection prevents us from beginning a transaction below (which requires a mutable
@@ -1908,7 +1916,7 @@ impl MemPoolDB {
19081916
"considered_txs" => u128::from(total_considered),
19091917
"elapsed_ms" => start_time.elapsed().as_millis()
19101918
);
1911-
Ok(total_considered)
1919+
Ok((total_considered, stop_reason))
19121920
}
19131921

19141922
pub fn conn(&self) -> &DBConn {

0 commit comments

Comments
 (0)