Skip to content

Conversation

@georgehao
Copy link
Member

No description provided.

@georgehao georgehao changed the title Improve sequencer metrics feat: improve sequencer metrics Dec 18, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Dec 18, 2025

Merging this PR will not alter performance

✅ 2 untouched benchmarks


Comparing feat/improve_sequencer_metrics (0bbc7b9) with main (b88371e)

Open in CodSpeed

Copy link
Collaborator

@frisitano frisitano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some comments inline. On a high level I think we should record the following metrics:

  • block_building_duration: the time it takes to build a non-empty block
  • empty_block_building_duration: the time it takes to build an empty block
  • consecutive_block_interval: the time between two consecutive blocks that are added to the canonical chain.

I'm not sure if you had a different idea about these metrics to please let me know if I have misunderstood something.

@georgehao
Copy link
Member Author

georgehao commented Jan 7, 2026

  • block_building_duration: the time it takes to build a non-empty block
  • empty_block_building_duration: the time it takes to build an empty block

Oh, I understand it is that:

if I want to check the block building duration, I will check the whole block building duration, then check the no-empty block building duration, then I will get the conclusion for it ( because the empty block building will always have a constant value, no sense to display this alone, and can calculate it from the all_block_building_duration and block_building_duration)

What do you think?

Copy link
Collaborator

@frisitano frisitano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment inline. I think the description you provided does not match the code.

@georgehao georgehao force-pushed the feat/improve_sequencer_metrics branch from 4107508 to d941f8b Compare January 12, 2026 08:57
Copy link
Collaborator

@frisitano frisitano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this solution doesn't work as expected. Please let me know if I made a mistake in my understanding.

.expect("signer must be present")
.sign_block(block.clone())?;
self.metric_handler.finish_block_building_recording();
self.metric_handler.finish_no_empty_block_building_recording();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function doesn't do anything because you already take the .block_building_start.take() in finish_all_block_building_recording.:

                let block = self
                    .sequencer
                    .as_mut()
                    .expect("sequencer must be present")
                    .finalize_payload_building(payload_id, &mut self.engine)
                    .await?

                self.metric_handler.finish_all_block_building_recording(); # block_building_start is taken here
                self.metric_handler.finish_block_building_interval_recording();

                if let Some(block) = block {
                    let block_info: L2BlockInfoWithL1Messages = (&block).into();
                    self.database
                        .update_l1_messages_from_l2_blocks(vec![block_info.clone()])
                        .await?;
                    self.signer
                        .as_mut()
                        .expect("signer must be present")
                        .sign_block(block.clone())?;
                     # this doesn't do anything because block_building_start is now None.
                    self.metric_handler.finish_no_empty_block_building_recording();
                    return Ok(Some(ChainOrchestratorEvent::BlockSequenced(block)));
                }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pub(crate) fn start_block_building_recording(&mut self) {
if self.block_building_meter.block_building_start.is_some() {
tracing::warn!(target: "scroll::chain_orchestrator", "block building recording is already ongoing, overwriting");
}
self.block_building_meter.block_building_start = Some(Instant::now());
}

I think no issue here, because it assign value here, calculates twice I think it's ok

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pub(crate) fn finish_all_block_building_recording(&mut self) {
let duration = self
.block_building_meter
.block_building_start
.take()
.map(|block_building_start| block_building_start.elapsed());
if let Some(duration) = duration {
self.block_building_meter
.metric
.all_block_building_duration
.record(duration.as_secs_f64());
}
}

You take self.block_building_meter.block_building_start.take() here.

You then try and take it again below which will always be None.

/// The duration of the current block building task if any.
pub(crate) fn finish_no_empty_block_building_recording(&mut self) {
let duration = self
.block_building_meter
.block_building_start
.take()
.map(|block_building_start| block_building_start.elapsed());
if let Some(duration) = duration {
self.block_building_meter.metric.block_building_duration.record(duration.as_secs_f64());
}
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that's right

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

struct Test {
    pub block_building_start: Option<Instant>,
}

impl Test {
    fn finish_no_empty_block_building_recording(&mut self) {
        if let Some(block_build_start) = self.block_building_start {
            let duration = block_build_start.elapsed();
            println!("Time taken: {:?}", duration);
        }
    }

    fn finish_all_block_building_recording(&mut self) {
        if let Some(block_build_start) = self.block_building_start {
            let duration = block_build_start.elapsed();
            println!("Time taken(2): {:?}", duration);
        }
    }
}
#[tokio::main]
async fn main() {
    let mut t = Test {
        block_building_start: Option::from(Instant::now()),
    };

    time::sleep(Duration::from_secs(2)).await;
    t.finish_no_empty_block_building_recording();

    time::sleep(Duration::from_secs(2)).await;
    t.finish_all_block_building_recording();
}

This is ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants