Skip to content

Commit f93844e

Browse files
Optimise concurrent block production (#5368)
* Optimise concurrent block production
1 parent 762dab2 commit f93844e

File tree

1 file changed

+41
-22
lines changed

1 file changed

+41
-22
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4166,21 +4166,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
41664166
(re_org_state.pre_state, re_org_state.state_root)
41674167
}
41684168
// Normal case: proposing a block atop the current head using the cache.
4169-
else if let Some((_, cached_state)) = self
4170-
.block_production_state
4171-
.lock()
4172-
.take()
4173-
.filter(|(cached_block_root, _)| *cached_block_root == head_block_root)
4169+
else if let Some((_, cached_state)) =
4170+
self.get_state_from_block_production_cache(head_block_root)
41744171
{
41754172
(cached_state.pre_state, cached_state.state_root)
41764173
}
41774174
// Fall back to a direct read of the snapshot cache.
4178-
else if let Some(pre_state) = self
4179-
.snapshot_cache
4180-
.try_read_for(BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT)
4181-
.and_then(|snapshot_cache| {
4182-
snapshot_cache.get_state_for_block_production(head_block_root)
4183-
})
4175+
else if let Some(pre_state) =
4176+
self.get_state_from_snapshot_cache_for_block_production(head_block_root)
41844177
{
41854178
warn!(
41864179
self.log,
@@ -4221,6 +4214,40 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
42214214
Ok((state, state_root_opt))
42224215
}
42234216

4217+
/// Get the state cached for block production *if* it matches `head_block_root`.
4218+
///
4219+
/// This will clear the cache regardless of whether the block root matches, so only call this if
4220+
/// you think the `head_block_root` is likely to match!
4221+
fn get_state_from_block_production_cache(
4222+
&self,
4223+
head_block_root: Hash256,
4224+
) -> Option<(Hash256, BlockProductionPreState<T::EthSpec>)> {
4225+
// Take care to drop the lock as quickly as possible.
4226+
let mut lock = self.block_production_state.lock();
4227+
let result = lock
4228+
.take()
4229+
.filter(|(cached_block_root, _)| *cached_block_root == head_block_root);
4230+
drop(lock);
4231+
result
4232+
}
4233+
4234+
/// Get a state for block production from the snapshot cache.
4235+
fn get_state_from_snapshot_cache_for_block_production(
4236+
&self,
4237+
head_block_root: Hash256,
4238+
) -> Option<BlockProductionPreState<T::EthSpec>> {
4239+
if let Some(lock) = self
4240+
.snapshot_cache
4241+
.try_read_for(BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT)
4242+
{
4243+
let result = lock.get_state_for_block_production(head_block_root);
4244+
drop(lock);
4245+
result
4246+
} else {
4247+
None
4248+
}
4249+
}
4250+
42244251
/// Fetch the beacon state to use for producing a block if a 1-slot proposer re-org is viable.
42254252
///
42264253
/// This function will return `None` if proposer re-orgs are disabled.
@@ -4313,12 +4340,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
43134340

43144341
// Only attempt a re-org if we hit the block production cache or snapshot cache.
43154342
let pre_state = self
4316-
.block_production_state
4317-
.lock()
4318-
.take()
4319-
.and_then(|(cached_block_root, state)| {
4320-
(cached_block_root == re_org_parent_block).then_some(state)
4321-
})
4343+
.get_state_from_block_production_cache(re_org_parent_block)
4344+
.map(|(_, state)| state)
43224345
.or_else(|| {
43234346
warn!(
43244347
self.log,
@@ -4327,11 +4350,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
43274350
"slot" => slot,
43284351
"block_root" => ?re_org_parent_block
43294352
);
4330-
self.snapshot_cache
4331-
.try_read_for(BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT)
4332-
.and_then(|snapshot_cache| {
4333-
snapshot_cache.get_state_for_block_production(re_org_parent_block)
4334-
})
4353+
self.get_state_from_snapshot_cache_for_block_production(re_org_parent_block)
43354354
})
43364355
.or_else(|| {
43374356
debug!(

0 commit comments

Comments
 (0)