From dde26f359f49d1d293364edbf0aa987d3eacb9ec Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Tue, 8 Sep 2020 09:23:48 +0200 Subject: [PATCH] better state cache reuse (#1612) --- beacon_chain/block_pools/chain_dag.nim | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/beacon_chain/block_pools/chain_dag.nim b/beacon_chain/block_pools/chain_dag.nim index 3474beba3..ba726eb15 100644 --- a/beacon_chain/block_pools/chain_dag.nim +++ b/beacon_chain/block_pools/chain_dag.nim @@ -560,12 +560,12 @@ proc get*(dag: ChainDAGRef, root: Eth2Digest): Option[BlockData] = none(BlockData) proc advanceSlots( - dag: ChainDAGRef, state: var StateData, slot: Slot, save: bool) = + dag: ChainDAGRef, state: var StateData, slot: Slot, cache: var StateCache, + save: bool) = # Given a state, advance it zero or more slots by applying empty slot # processing doAssert state.data.data.slot <= slot - var cache = getStateCache(state.blck, state.data.data.slot.epoch) while state.data.data.slot < slot: # Process slots one at a time in case afterUpdate needs to see empty states advance_slot(state.data, dag.updateFlags, cache) @@ -575,7 +575,8 @@ proc advanceSlots( proc applyBlock( dag: ChainDAGRef, - state: var StateData, blck: BlockData, flags: UpdateFlags, save: bool): bool = + state: var StateData, blck: BlockData, flags: UpdateFlags, + cache: var StateCache, save: bool): bool = # Apply a single block to the state - the state must be positioned at the # parent of the block with a slot lower than the one of the block being # applied @@ -583,14 +584,13 @@ proc applyBlock( # `state_transition` can handle empty slots, but we want to potentially save # some of the empty slot states - dag.advanceSlots(state, blck.data.message.slot, save) + dag.advanceSlots(state, blck.data.message.slot, cache, save) var statePtr = unsafeAddr state # safe because `restore` is locally scoped func restore(v: var HashedBeaconState) = doAssert (addr(statePtr.data) == addr v) statePtr[] = dag.headState - var cache = getStateCache(state.blck, state.data.data.slot.epoch) let ok = state_transition( dag.runtimePreset, state.data, blck.data, cache, flags + dag.updateFlags + {slotProcessed}, restore) @@ -616,10 +616,12 @@ proc updateStateData*( if state.blck == bs.blck and state.data.data.slot <= bs.slot: # The block is the same and we're at an early enough slot - advance the # state with empty slot processing until the slot is correct - dag.advanceSlots(state, bs.slot, true) + dag.advanceSlots(state, bs.slot, cache, true) return + warn "UpdateStateData miss", bs, stateBlock = state.blck, stateSlot = state.data.data.slot + # Either the state is too new or was created by applying a different block. # We'll now resort to loading the state from the database then reapplying # blocks until we reach the desired point in time. @@ -658,12 +660,12 @@ proc updateStateData*( # database, we can skip certain checks that have already been performed # before adding the block to the database. let ok = - dag.applyBlock(state, dag.get(ancestors[i]), {}, false) + dag.applyBlock(state, dag.get(ancestors[i]), {}, cache, false) doAssert ok, "Blocks in database should never fail to apply.." # We save states here - blocks were guaranteed to have passed through the save # function once at least, but not so for empty slots! - dag.advanceSlots(state, bs.slot, true) + dag.advanceSlots(state, bs.slot, cache, true) beacon_state_rewinds.inc()