Skip to content

Commit

Permalink
perf(state): batch save State (cometbft#1735)
Browse files Browse the repository at this point in the history
* done stateDB writes batching

* remove forgotten debug print

* remove forgotten comments

* format code

* add a changelog entry

* fix changelog

---------

Co-authored-by: werty144 <[email protected]>
  • Loading branch information
melekes and werty144 authored Dec 7, 2023
1 parent ce0215c commit 76b1cce
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- `[types]` Validate `Validator#Address` in `ValidateBasic` ([\#1715](https://github.com/cometbft/cometbft/pull/1715))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- `[state]` Save the state using a single DB batch ([\#1735](https://github.com/cometbft/cometbft/pull/1735))
11 changes: 10 additions & 1 deletion internal/state/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,16 @@ func ValidateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, params types.V
// store.go, exported exclusively and explicitly for testing.
func SaveValidatorsInfo(db dbm.DB, height, lastHeightChanged int64, valSet *types.ValidatorSet) error {
stateStore := dbStore{db, StoreOptions{DiscardABCIResponses: false}}
return stateStore.saveValidatorsInfo(height, lastHeightChanged, valSet)
batch := stateStore.db.NewBatch()
err := stateStore.saveValidatorsInfo(height, lastHeightChanged, valSet, batch)
if err != nil {
return err
}
err = batch.WriteSync()
if err != nil {
return err
}
return nil
}

// FindMinBlockRetainHeight is an alias for the private
Expand Down
54 changes: 38 additions & 16 deletions internal/state/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,61 +209,83 @@ func (store dbStore) Save(state State) error {
}

func (store dbStore) save(state State, key []byte) error {
batch := store.db.NewBatch()
defer func(batch dbm.Batch) {
err := batch.Close()
if err != nil {
panic(err)
}
}(batch)
nextHeight := state.LastBlockHeight + 1
// If first block, save validators for the block.
if nextHeight == 1 {
nextHeight = state.InitialHeight
// This extra logic due to validator set changes being delayed 1 block.
// It may get overwritten due to InitChain validator updates.
if err := store.saveValidatorsInfo(nextHeight, nextHeight, state.Validators); err != nil {
if err := store.saveValidatorsInfo(nextHeight, nextHeight, state.Validators, batch); err != nil {
return err
}
}
// Save next validators.
if err := store.saveValidatorsInfo(nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators); err != nil {
if err := store.saveValidatorsInfo(nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators, batch); err != nil {
return err
}

// Save next consensus params.
if err := store.saveConsensusParamsInfo(nextHeight,
state.LastHeightConsensusParamsChanged, state.ConsensusParams); err != nil {
state.LastHeightConsensusParamsChanged, state.ConsensusParams, batch); err != nil {
return err
}
err := store.db.SetSync(key, state.Bytes())
if err != nil {
if err := batch.Set(key, state.Bytes()); err != nil {
return err
}

if err := batch.WriteSync(); err != nil {
panic(err)
}
return nil
}

// BootstrapState saves a new state, used e.g. by state sync when starting from non-zero height.
func (store dbStore) Bootstrap(state State) error {
batch := store.db.NewBatch()
defer func(batch dbm.Batch) {
err := batch.Close()
if err != nil {
panic(err)
}
}(batch)
height := state.LastBlockHeight + 1
if height == 1 {
height = state.InitialHeight
}

if height > 1 && !state.LastValidators.IsNilOrEmpty() {
if err := store.saveValidatorsInfo(height-1, height-1, state.LastValidators); err != nil {
if err := store.saveValidatorsInfo(height-1, height-1, state.LastValidators, batch); err != nil {
return err
}
}

if err := store.saveValidatorsInfo(height, height, state.Validators); err != nil {
if err := store.saveValidatorsInfo(height, height, state.Validators, batch); err != nil {
return err
}

if err := store.saveValidatorsInfo(height+1, height+1, state.NextValidators); err != nil {
if err := store.saveValidatorsInfo(height+1, height+1, state.NextValidators, batch); err != nil {
return err
}

if err := store.saveConsensusParamsInfo(height,
state.LastHeightConsensusParamsChanged, state.ConsensusParams); err != nil {
state.LastHeightConsensusParamsChanged, state.ConsensusParams, batch); err != nil {
return err
}

return store.db.SetSync(stateKey, state.Bytes())
if err := batch.Set(stateKey, state.Bytes()); err != nil {
return err
}

if err := batch.WriteSync(); err != nil {
panic(err)
}

return batch.Close()
}

// PruneStates deletes states between the given heights (including from, excluding to). It is not
Expand Down Expand Up @@ -742,7 +764,7 @@ func loadValidatorsInfo(db dbm.DB, height int64) (*cmtstate.ValidatorsInfo, erro
// `height` is the effective height for which the validator is responsible for
// signing. It should be called from s.Save(), right before the state itself is
// persisted.
func (store dbStore) saveValidatorsInfo(height, lastHeightChanged int64, valSet *types.ValidatorSet) error {
func (store dbStore) saveValidatorsInfo(height, lastHeightChanged int64, valSet *types.ValidatorSet, batch dbm.Batch) error {
if lastHeightChanged > height {
return errors.New("lastHeightChanged cannot be greater than ValidatorsInfo height")
}
Expand All @@ -764,7 +786,7 @@ func (store dbStore) saveValidatorsInfo(height, lastHeightChanged int64, valSet
return err
}

err = store.db.Set(calcValidatorsKey(height), bz)
err = batch.Set(calcValidatorsKey(height), bz)
if err != nil {
return err
}
Expand Down Expand Up @@ -828,7 +850,7 @@ func (store dbStore) loadConsensusParamsInfo(height int64) (*cmtstate.ConsensusP
// It should be called from s.Save(), right before the state itself is persisted.
// If the consensus params did not change after processing the latest block,
// only the last height for which they changed is persisted.
func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params types.ConsensusParams) error {
func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params types.ConsensusParams, batch dbm.Batch) error {
paramsInfo := &cmtstate.ConsensusParamsInfo{
LastHeightChanged: changeHeight,
}
Expand All @@ -841,7 +863,7 @@ func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, par
return err
}

err = store.db.Set(calcConsensusParamsKey(nextHeight), bz)
err = batch.Set(calcConsensusParamsKey(nextHeight), bz)
if err != nil {
return err
}
Expand Down

0 comments on commit 76b1cce

Please sign in to comment.