Skip to content

Commit b7d8815

Browse files
perf(prune): use delete_current_duplicates for MerkleChangeSets tables (#20230)
1 parent b91cd8f commit b7d8815

File tree

3 files changed

+60
-8
lines changed

3 files changed

+60
-8
lines changed

crates/prune/prune/src/db_ext.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use crate::PruneLimiter;
22
use reth_db_api::{
33
cursor::{DbCursorRO, DbCursorRW, RangeWalker},
4-
table::{Table, TableRow},
5-
transaction::DbTxMut,
4+
table::{DupSort, Table, TableRow},
5+
transaction::{DbTx, DbTxMut},
66
DatabaseError,
77
};
88
use std::{fmt::Debug, ops::RangeBounds};
99
use tracing::debug;
1010

11-
pub(crate) trait DbTxPruneExt: DbTxMut {
11+
pub(crate) trait DbTxPruneExt: DbTxMut + DbTx {
1212
/// Prune the table for the specified pre-sorted key iterator.
1313
///
1414
/// Returns number of rows pruned.
@@ -123,9 +123,55 @@ pub(crate) trait DbTxPruneExt: DbTxMut {
123123

124124
Ok(false)
125125
}
126+
127+
/// Prune a DUPSORT table for the specified key range.
128+
///
129+
/// Returns number of rows pruned.
130+
fn prune_dupsort_table_with_range<T: DupSort>(
131+
&self,
132+
keys: impl RangeBounds<T::Key> + Clone + Debug,
133+
limiter: &mut PruneLimiter,
134+
mut delete_callback: impl FnMut(TableRow<T>),
135+
) -> Result<(usize, bool), DatabaseError> {
136+
let starting_entries = self.entries::<T>()?;
137+
let mut cursor = self.cursor_dup_write::<T>()?;
138+
let mut walker = cursor.walk_range(keys)?;
139+
140+
let done = loop {
141+
if limiter.is_limit_reached() {
142+
debug!(
143+
target: "providers::db",
144+
?limiter,
145+
deleted_entries_limit = %limiter.is_deleted_entries_limit_reached(),
146+
time_limit = %limiter.is_time_limit_reached(),
147+
table = %T::NAME,
148+
"Pruning limit reached"
149+
);
150+
break false
151+
}
152+
153+
let Some(res) = walker.next() else { break true };
154+
let row = res?;
155+
156+
walker.delete_current_duplicates()?;
157+
limiter.increment_deleted_entries_count();
158+
delete_callback(row);
159+
};
160+
161+
debug!(
162+
target: "providers::db",
163+
table=?T::NAME,
164+
cursor_current=?cursor.current(),
165+
"done walking",
166+
);
167+
168+
let ending_entries = self.entries::<T>()?;
169+
170+
Ok((starting_entries - ending_entries, done))
171+
}
126172
}
127173

128-
impl<Tx> DbTxPruneExt for Tx where Tx: DbTxMut {}
174+
impl<Tx> DbTxPruneExt for Tx where Tx: DbTxMut + DbTx {}
129175

130176
#[cfg(test)]
131177
mod tests {

crates/prune/prune/src/segments/user/merkle_change_sets.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,9 @@ where
7171

7272
let mut last_storages_pruned_block = None;
7373
let (storages_pruned, done) =
74-
provider.tx_ref().prune_table_with_range::<tables::StoragesTrieChangeSets>(
74+
provider.tx_ref().prune_dupsort_table_with_range::<tables::StoragesTrieChangeSets>(
7575
storage_range,
7676
&mut limiter,
77-
|_| false,
7877
|(BlockNumberHashedAddress((block_number, _)), _)| {
7978
last_storages_pruned_block = Some(block_number);
8079
},
@@ -90,10 +89,9 @@ where
9089
.unwrap_or(block_range_end);
9190

9291
let (accounts_pruned, done) =
93-
provider.tx_ref().prune_table_with_range::<tables::AccountsTrieChangeSets>(
92+
provider.tx_ref().prune_dupsort_table_with_range::<tables::AccountsTrieChangeSets>(
9493
block_range,
9594
&mut limiter,
96-
|_| false,
9795
|row| last_accounts_pruned_block = row.0,
9896
)?;
9997

crates/storage/db-api/src/cursor.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,14 @@ impl<T: Table, CURSOR: DbCursorRW<T> + DbCursorRO<T>> RangeWalker<'_, T, CURSOR>
318318
}
319319
}
320320

321+
impl<T: DupSort, CURSOR: DbDupCursorRW<T> + DbCursorRO<T>> RangeWalker<'_, T, CURSOR> {
322+
/// Delete all duplicate entries for current key that walker points to.
323+
pub fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> {
324+
self.start.take();
325+
self.cursor.delete_current_duplicates()
326+
}
327+
}
328+
321329
/// Provides an iterator to `Cursor` when handling a `DupSort` table.
322330
///
323331
/// Reason why we have two lifetimes is to distinguish between `'cursor` lifetime

0 commit comments

Comments
 (0)