From 739ea1590963dbddc788bf05429cb6045462fc4e Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Fri, 15 Dec 2023 15:27:31 +0700 Subject: [PATCH 1/3] feat: track and call state.hashTreeRoot() in prepareNextSlot --- .../src/chain/blocks/verifyBlocksStateTransitionOnly.ts | 2 +- packages/beacon-node/src/chain/prepareNextSlot.ts | 4 ++++ .../src/chain/produceBlock/computeNewStateRoot.ts | 6 +++++- packages/beacon-node/src/metrics/metrics/lodestar.ts | 3 ++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts index 2afc9543f847..709ad0c02b27 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts @@ -57,7 +57,7 @@ export async function verifyBlocksStateTransitionOnly( metrics ); - const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer(); + const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({source: "block_transition"}); const stateRoot = postState.hashTreeRoot(); hashTreeRootTimer?.(); diff --git a/packages/beacon-node/src/chain/prepareNextSlot.ts b/packages/beacon-node/src/chain/prepareNextSlot.ts index 43fac1d1b120..86461121e4c9 100644 --- a/packages/beacon-node/src/chain/prepareNextSlot.ts +++ b/packages/beacon-node/src/chain/prepareNextSlot.ts @@ -104,6 +104,10 @@ export class PrepareNextSlotScheduler { RegenCaller.precomputeEpoch ); + const hashTreeRootTimer = this.metrics?.stateHashTreeRootTime.startTimer({source: "prepare_next_slot"}); + prepareState.hashTreeRoot(); + hashTreeRootTimer?.(); + // assuming there is no reorg, it caches the checkpoint state & helps avoid doing a full state transition in the next slot // + when gossip block comes, we need to validate and run state transition // + if next slot is a skipped slot, it'd help getting target checkpoint state faster to validate attestations diff --git a/packages/beacon-node/src/chain/produceBlock/computeNewStateRoot.ts b/packages/beacon-node/src/chain/produceBlock/computeNewStateRoot.ts index fcc2a97b42b1..f5d02dbf9b6f 100644 --- a/packages/beacon-node/src/chain/produceBlock/computeNewStateRoot.ts +++ b/packages/beacon-node/src/chain/produceBlock/computeNewStateRoot.ts @@ -44,5 +44,9 @@ export function computeNewStateRoot( const {attestations, syncAggregate, slashing} = postState.proposerRewards; const proposerReward = BigInt(attestations + syncAggregate + slashing); - return {newStateRoot: postState.hashTreeRoot(), proposerReward}; + const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({source: "compute_new_state_root"}); + const newStateRoot = postState.hashTreeRoot(); + hashTreeRootTimer?.(); + + return {newStateRoot, proposerReward}; } diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 64d43af9001d..886a8048adbb 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -304,10 +304,11 @@ export function createLodestarMetrics( help: "Time to call commit after process a single block in seconds", buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1], }), - stateHashTreeRootTime: register.histogram({ + stateHashTreeRootTime: register.histogram<"source">({ name: "lodestar_stfn_hash_tree_root_seconds", help: "Time to compute the hash tree root of a post state in seconds", buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1], + labelNames: ["source"], }), preStateBalancesNodesPopulatedMiss: register.gauge<"source">({ name: "lodestar_stfn_balances_nodes_populated_miss_total", From a68c9601ce4d56dde6d9a626b71b2479a1ac2c4d Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Fri, 15 Dec 2023 16:05:26 +0700 Subject: [PATCH 2/3] fix: correct stateHashTreeRootTime bucket --- packages/beacon-node/src/metrics/metrics/lodestar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 886a8048adbb..8a22fe8f0a9b 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -307,7 +307,7 @@ export function createLodestarMetrics( stateHashTreeRootTime: register.histogram<"source">({ name: "lodestar_stfn_hash_tree_root_seconds", help: "Time to compute the hash tree root of a post state in seconds", - buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1], + buckets: [0.05, 0.1, 0.2, 0.5, 1, 1.5], labelNames: ["source"], }), preStateBalancesNodesPopulatedMiss: register.gauge<"source">({ From 291d80012582fc002c2e51ba669e5b5cb43a3408 Mon Sep 17 00:00:00 2001 From: Tuyen Nguyen Date: Fri, 15 Dec 2023 16:22:25 +0700 Subject: [PATCH 3/3] docs: add more comment for the fix --- packages/beacon-node/src/chain/prepareNextSlot.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/beacon-node/src/chain/prepareNextSlot.ts b/packages/beacon-node/src/chain/prepareNextSlot.ts index 86461121e4c9..ce8e720cd766 100644 --- a/packages/beacon-node/src/chain/prepareNextSlot.ts +++ b/packages/beacon-node/src/chain/prepareNextSlot.ts @@ -104,6 +104,8 @@ export class PrepareNextSlotScheduler { RegenCaller.precomputeEpoch ); + // cache HashObjects for faster hashTreeRoot() later, especially for computeNewStateRoot() if we need to produce a block at slot 0 of epoch + // see https://github.com/ChainSafe/lodestar/issues/6194 const hashTreeRootTimer = this.metrics?.stateHashTreeRootTime.startTimer({source: "prepare_next_slot"}); prepareState.hashTreeRoot(); hashTreeRootTimer?.();