Skip to content

Commit 4021b46

Browse files
authored
feat(l1): improve rebuilding speed during snap sync (lambdaclass#2447)
**Motivation** After recent changes in main, rebuilding now takes a lot longer than state sync. This PR aims to mitigate this hit by introducing other performance upgrades <!-- Why does this pull request exist? What are its goals? --> **Description** * Increase parallelism when rebuilding storages * Reduce intermediate hashing when rebuilding state tries <!-- A clear and concise general description of the changes this PR introduces --> These changes have increased storage rebuild speed to around the same as before the changes to store, and has reduced time estimates for state rebuild, but doesn't manage to make the state rebuild keep up with the state sync. These changes have not affected state sync speed <!-- Link to issues: Resolves lambdaclass#111, Resolves lambdaclass#222 --> Closes #issue_number
1 parent 6d71c28 commit 4021b46

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

crates/networking/p2p/sync/trie_rebuild.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,20 @@ use tracing::{info, warn};
2121
use crate::sync::seconds_to_readable;
2222

2323
use super::{
24-
SyncError, MAX_CHANNEL_MESSAGES, MAX_CHANNEL_READS, MAX_PARALLEL_FETCHES,
25-
SHOW_PROGRESS_INTERVAL_DURATION, STATE_TRIE_SEGMENTS_END, STATE_TRIE_SEGMENTS_START,
24+
SyncError, MAX_CHANNEL_MESSAGES, MAX_CHANNEL_READS, SHOW_PROGRESS_INTERVAL_DURATION,
25+
STATE_TRIE_SEGMENTS_END, STATE_TRIE_SEGMENTS_START,
2626
};
2727

2828
/// The storage root used to indicate that the storage to be rebuilt is not complete
2929
/// This will tell the rebuilder to skip storage root validations for this trie
3030
/// The storage should be queued for rebuilding by the sender
3131
pub(crate) const REBUILDER_INCOMPLETE_STORAGE_ROOT: H256 = H256::zero();
3232

33+
/// Max storages to rebuild in parallel
34+
const MAX_PARALLEL_REBUILDS: usize = 15;
35+
36+
const MAX_SNAPSHOT_READS_WITHOUT_COMMIT: usize = 5;
37+
3338
/// Represents the permanently ongoing background trie rebuild process
3439
/// This process will be started whenever a state sync is initiated and will be
3540
/// kept alive throughout sync cycles, only stopping once the tries are fully rebuilt or the node is stopped
@@ -159,10 +164,12 @@ async fn rebuild_state_trie_segment(
159164
cancel_token: CancellationToken,
160165
) -> Result<(H256, H256), SyncError> {
161166
let mut state_trie = store.open_state_trie(root);
167+
let mut snapshot_reads_since_last_commit = 0;
162168
loop {
163169
if cancel_token.is_cancelled() {
164170
break;
165171
}
172+
snapshot_reads_since_last_commit += 1;
166173
let mut batch = store.read_account_snapshot(start)?;
167174
// Remove out of bounds elements
168175
batch.retain(|(hash, _)| *hash <= STATE_TRIE_SEGMENTS_END[segment_number]);
@@ -176,7 +183,10 @@ async fn rebuild_state_trie_segment(
176183
for (hash, account) in batch.iter() {
177184
state_trie.insert(hash.0.to_vec(), account.encode_to_vec())?;
178185
}
179-
root = state_trie.hash()?;
186+
if snapshot_reads_since_last_commit > MAX_SNAPSHOT_READS_WITHOUT_COMMIT {
187+
snapshot_reads_since_last_commit = 0;
188+
state_trie.hash()?;
189+
}
180190
// Return if we have no more snapshot accounts to process for this segemnt
181191
if unfilled_batch {
182192
let state_sync_complete = store
@@ -190,6 +200,7 @@ async fn rebuild_state_trie_segment(
190200
break;
191201
}
192202
}
203+
root = state_trie.hash()?;
193204
Ok((root, start))
194205
}
195206

@@ -221,7 +232,7 @@ async fn rebuild_storage_trie_in_background(
221232

222233
// Spawn tasks to rebuild current storages
223234
let mut rebuild_tasks = JoinSet::new();
224-
for _ in 0..MAX_PARALLEL_FETCHES {
235+
for _ in 0..MAX_PARALLEL_REBUILDS {
225236
if pending_storages.is_empty() {
226237
break;
227238
}
@@ -253,8 +264,11 @@ async fn rebuild_storage_trie(
253264
) -> Result<(), SyncError> {
254265
let mut start = H256::zero();
255266
let mut storage_trie = store.open_storage_trie(account_hash, *EMPTY_TRIE_HASH);
267+
let mut snapshot_reads_since_last_commit = 0;
256268
loop {
269+
snapshot_reads_since_last_commit += 1;
257270
let batch = store.read_storage_snapshot(account_hash, start).await?;
271+
258272
let unfilled_batch = batch.len() < MAX_SNAPSHOT_READS;
259273
// Update start
260274
if let Some(last) = batch.last() {
@@ -265,9 +279,12 @@ async fn rebuild_storage_trie(
265279
for (key, val) in batch {
266280
storage_trie.insert(key.0.to_vec(), val.encode_to_vec())?;
267281
}
268-
storage_trie.hash()?;
282+
if snapshot_reads_since_last_commit > MAX_SNAPSHOT_READS_WITHOUT_COMMIT {
283+
snapshot_reads_since_last_commit = 0;
284+
storage_trie.hash()?;
285+
}
269286

270-
// Return if we have no more snapshot accounts to process for this segemnt
287+
// Return if we have no more snapshot values to process for this storage
271288
if unfilled_batch {
272289
break;
273290
}

0 commit comments

Comments
 (0)