Skip to content

Commit df3a9bd

Browse files
authored
feat(l2): enhance monitor performance (#3757)
**Motivation** If a sequencer runs for a long time, it stops, and we run it again activating the monitor, it takes a long time to start and is slow. <!-- Why does this pull request exist? What are its goals? --> **Description** Makes the monitor load and work faster by simplifying the batches processing. <!-- A clear and concise general description of the changes this PR introduces --> **How to Test** - Run a Sequencer (I suggest `make restart` in `crates/l2`). - Run the prover with `make init-prover` in `crates/l2`. - Let the sequencer ran for some time (at least 60 batches) - Kill the sequencer - Add `--monitor` to the `init-l2-no-metrics` target in `crates/l2/Makefile`. - Run `make init-l2-no-metrics` <!-- Link to issues: Resolves #111, Resolves #222 -->
1 parent c984865 commit df3a9bd

File tree

2 files changed

+55
-25
lines changed

2 files changed

+55
-25
lines changed

crates/l2/monitor/widget/batches.rs

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use crate::{
1414
sequencer::errors::MonitorError,
1515
};
1616

17+
const BATCH_WINDOW_SIZE: usize = 50;
18+
1719
#[derive(Clone, Default)]
1820
pub struct BatchesTable {
1921
pub state: TableState,
@@ -44,10 +46,11 @@ impl BatchesTable {
4446
rollup_store,
4547
)
4648
.await?;
47-
new_latest_batches.truncate(50);
49+
new_latest_batches.truncate(BATCH_WINDOW_SIZE);
4850

4951
let n_new_latest_batches = new_latest_batches.len();
50-
self.items.truncate(50 - n_new_latest_batches);
52+
self.items
53+
.truncate(BATCH_WINDOW_SIZE - n_new_latest_batches);
5154
self.refresh_items(rollup_store).await?;
5255
self.items.extend_from_slice(&new_latest_batches);
5356
self.items.rotate_right(n_new_latest_batches);
@@ -60,18 +63,27 @@ impl BatchesTable {
6063
return Ok(());
6164
}
6265

63-
let mut from = self.items.last().ok_or(MonitorError::NoItemsInTable)?.0 - 1;
64-
65-
let refreshed_batches = Self::get_batches(
66-
&mut from,
67-
self.items.first().ok_or(MonitorError::NoItemsInTable)?.0,
68-
rollup_store,
69-
)
70-
.await?;
66+
let mut refreshed_batches = Vec::new();
67+
68+
for batch in self.items.iter() {
69+
if batch.3.is_some() && batch.4.is_some() {
70+
// Both commit and verify tx hashes are present
71+
refreshed_batches.push(*batch);
72+
} else {
73+
let batch_number = batch.0;
74+
let new_batch = rollup_store
75+
.get_batch(batch_number)
76+
.await
77+
.map_err(|e| MonitorError::GetBatchByNumber(batch_number, e))?
78+
.ok_or(MonitorError::BatchNotFound(batch_number))?;
79+
80+
refreshed_batches.push(Self::process_batch(&new_batch));
81+
}
82+
}
7183

72-
let refreshed_items = Self::process_batches(refreshed_batches).await;
84+
Self::reorder_batches(&mut refreshed_batches);
7385

74-
self.items = refreshed_items;
86+
self.items = refreshed_batches;
7587

7688
Ok(())
7789
}
@@ -87,10 +99,18 @@ impl BatchesTable {
8799
.await
88100
.map_err(|_| MonitorError::GetLatestBatch)?;
89101

102+
*last_l2_batch_fetched = (*last_l2_batch_fetched).max(
103+
last_l2_batch_number.saturating_sub(
104+
BATCH_WINDOW_SIZE
105+
.try_into()
106+
.map_err(|_| MonitorError::BatchWindow)?,
107+
),
108+
);
109+
90110
let new_batches =
91111
Self::get_batches(last_l2_batch_fetched, last_l2_batch_number, rollup_store).await?;
92112

93-
Ok(Self::process_batches(new_batches).await)
113+
Ok(Self::process_batches(new_batches))
94114
}
95115

96116
async fn get_batches(
@@ -115,24 +135,32 @@ impl BatchesTable {
115135
Ok(new_batches)
116136
}
117137

118-
async fn process_batches(
138+
fn process_batch(batch: &Batch) -> (u64, u64, usize, Option<H256>, Option<H256>) {
139+
(
140+
batch.number,
141+
batch.last_block - batch.first_block + 1,
142+
batch.message_hashes.len(),
143+
batch.commit_tx,
144+
batch.verify_tx,
145+
)
146+
}
147+
148+
#[expect(clippy::type_complexity)]
149+
fn reorder_batches(new_blocks_processed: &mut [(u64, u64, usize, Option<H256>, Option<H256>)]) {
150+
new_blocks_processed
151+
.sort_by(|(number_a, _, _, _, _), (number_b, _, _, _, _)| number_b.cmp(number_a));
152+
}
153+
154+
#[expect(clippy::type_complexity)]
155+
fn process_batches(
119156
new_batches: Vec<Batch>,
120157
) -> Vec<(u64, u64, usize, Option<H256>, Option<H256>)> {
121158
let mut new_blocks_processed = new_batches
122159
.iter()
123-
.map(|batch| {
124-
(
125-
batch.number,
126-
batch.last_block - batch.first_block + 1,
127-
batch.message_hashes.len(),
128-
batch.commit_tx,
129-
batch.verify_tx,
130-
)
131-
})
160+
.map(Self::process_batch)
132161
.collect::<Vec<_>>();
133162

134-
new_blocks_processed
135-
.sort_by(|(number_a, _, _, _, _), (number_b, _, _, _, _)| number_b.cmp(number_a));
163+
Self::reorder_batches(&mut new_blocks_processed);
136164

137165
new_blocks_processed
138166
}

crates/l2/sequencer/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,4 +347,6 @@ pub enum MonitorError {
347347
NoItemsInTable,
348348
#[error("RPC List can't be empty")]
349349
RPCListEmpty,
350+
#[error("Error converting batch window")]
351+
BatchWindow,
350352
}

0 commit comments

Comments
 (0)