Skip to content

Commit

Permalink
worker: reused triePrefetch when multi-fillTransactions to mine a block.
Browse files Browse the repository at this point in the history
avoid too much trie prefetch routines when several fillTransactions are called.
  • Loading branch information
setunapo committed Nov 25, 2022
1 parent d87d697 commit f35abea
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 12 deletions.
19 changes: 19 additions & 0 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,25 @@ func (s *StateDB) EnableWriteOnSharedStorage() {
s.writeOnSharedStorage = true
}

// In mining mode, we will try multi-fillTransactions to get the most profitable one.
// StateDB will be created for each fillTransactions with same block height.
// Share a single triePrefetcher to avoid too much prefetch routines.
func (s *StateDB) TransferPrefetcher(prev *StateDB) {
if prev == nil {
return
}
var fetcher *triePrefetcher

prev.prefetcherLock.Lock()
fetcher = prev.prefetcher
prev.prefetcher = nil
prev.prefetcherLock.Unlock()

s.prefetcherLock.Lock()
s.prefetcher = fetcher
s.prefetcherLock.Unlock()
}

// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
// state trie concurrently while the state is mutated so that when we reach the
// commit phase, most of the needed data is already hot.
Expand Down
32 changes: 20 additions & 12 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,14 +718,19 @@ func (w *worker) resultLoop() {
}

// makeEnv creates a new environment for the sealing block.
func (w *worker) makeEnv(parent *types.Block, header *types.Header, coinbase common.Address) (*environment, error) {
func (w *worker) makeEnv(parent *types.Block, header *types.Header, coinbase common.Address,
prevEnv *environment) (*environment, error) {
// Retrieve the parent state to execute on top and start a prefetcher for
// the miner to speed block sealing up a bit
state, err := w.chain.StateAtWithSharedPool(parent.Root())
if err != nil {
return nil, err
}
state.StartPrefetcher("miner")
if prevEnv == nil {
state.StartPrefetcher("miner")
} else {
state.TransferPrefetcher(prevEnv.state)
}

// Note the passed coinbase may be different with header.Coinbase.
env := &environment{
Expand Down Expand Up @@ -941,6 +946,7 @@ type generateParams struct {
random common.Hash // The randomness generated by beacon chain, empty before the merge
noUncle bool // Flag whether the uncle block inclusion is allowed
noExtra bool // Flag whether the extra field assignment is allowed
prevWork *environment
}

// prepareWork constructs the sealing task according to the given parameters,
Expand Down Expand Up @@ -999,7 +1005,7 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
// Could potentially happen if starting to mine in an odd state.
// Note genParams.coinbase can be different with header.Coinbase
// since clique algorithm can modify the coinbase field in header.
env, err := w.makeEnv(parent, header, genParams.coinbase)
env, err := w.makeEnv(parent, header, genParams.coinbase, genParams.prevWork)
if err != nil {
log.Error("Failed to create sealing context", "err", err)
return nil, err
Expand Down Expand Up @@ -1105,27 +1111,29 @@ func (w *worker) commitWork(interruptCh chan int32, timestamp int64) {
// validator can try several times to get the most profitable block,
// as long as the timestamp is not reached.
workList := make([]*environment, 0, 10)
var bestWork *environment
var prevWork *environment
// workList clean up
defer func() {
for _, w := range workList {
for _, wk := range workList {
// only keep the best work, discard others.
if w == bestWork {
if wk == w.current {
continue
}
w.discard()
wk.discard()
}
}()

LOOP:
for {
work, err := w.prepareWork(&generateParams{
timestamp: uint64(timestamp),
coinbase: coinbase,
prevWork: prevWork,
})
if err != nil {
return
}

prevWork = work
workList = append(workList, work)

delay := w.engine.Delay(w.chain, work.header, &w.config.DelayLeftOver)
Expand Down Expand Up @@ -1215,13 +1223,13 @@ LOOP:
}
}
// get the most profitable work
bestWork = workList[0]
bestWork := workList[0]
bestReward := new(big.Int)
for i, w := range workList {
balance := w.state.GetBalance(consensus.SystemAddress)
for i, wk := range workList {
balance := wk.state.GetBalance(consensus.SystemAddress)
log.Debug("Get the most profitable work", "index", i, "balance", balance, "bestReward", bestReward)
if balance.Cmp(bestReward) > 0 {
bestWork = w
bestWork = wk
bestReward = balance
}
}
Expand Down

0 comments on commit f35abea

Please sign in to comment.