From 2a1fc3d155870ba2e42f108a232b4b6a3ad9d939 Mon Sep 17 00:00:00 2001 From: Ryan Schneider Date: Mon, 16 Apr 2018 00:56:20 -0700 Subject: [PATCH] miner: remove contention on currentMu for pending data retrievals (#16497) --- miner/worker.go | 51 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/miner/worker.go b/miner/worker.go index 15395ae0b..48b0b2765 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -117,6 +117,10 @@ type worker struct { currentMu sync.Mutex current *Work + snapshotMu sync.RWMutex + snapshotBlock *types.Block + snapshotState *state.StateDB + uncleMu sync.Mutex possibleUncles map[common.Hash]*types.Block @@ -171,32 +175,28 @@ func (self *worker) setExtra(extra []byte) { } func (self *worker) pending() (*types.Block, *state.StateDB) { + if atomic.LoadInt32(&self.mining) == 0 { + // return a snapshot to avoid contention on currentMu mutex + self.snapshotMu.RLock() + defer self.snapshotMu.RUnlock() + return self.snapshotBlock, self.snapshotState.Copy() + } + self.currentMu.Lock() defer self.currentMu.Unlock() - - if atomic.LoadInt32(&self.mining) == 0 { - return types.NewBlock( - self.current.header, - self.current.txs, - nil, - self.current.receipts, - ), self.current.state.Copy() - } return self.current.Block, self.current.state.Copy() } func (self *worker) pendingBlock() *types.Block { + if atomic.LoadInt32(&self.mining) == 0 { + // return a snapshot to avoid contention on currentMu mutex + self.snapshotMu.RLock() + defer self.snapshotMu.RUnlock() + return self.snapshotBlock + } + self.currentMu.Lock() defer self.currentMu.Unlock() - - if atomic.LoadInt32(&self.mining) == 0 { - return types.NewBlock( - self.current.header, - self.current.txs, - nil, - self.current.receipts, - ) - } return self.current.Block } @@ -268,6 +268,7 @@ func (self *worker) update() { txset := types.NewTransactionsByPriceAndNonce(self.current.signer, txs) self.current.commitTransactions(self.mux, txset, self.chain, self.coinbase) + self.updateSnapshot() self.currentMu.Unlock() } else { // If we're mining, but nothing is being processed, wake on new transactions @@ -489,6 +490,7 @@ func (self *worker) commitNewWork() { self.unconfirmed.Shift(work.Block.NumberU64() - 1) } self.push(work) + self.updateSnapshot() } func (self *worker) commitUncle(work *Work, uncle *types.Header) error { @@ -506,6 +508,19 @@ func (self *worker) commitUncle(work *Work, uncle *types.Header) error { return nil } +func (self *worker) updateSnapshot() { + self.snapshotMu.Lock() + defer self.snapshotMu.Unlock() + + self.snapshotBlock = types.NewBlock( + self.current.header, + self.current.txs, + nil, + self.current.receipts, + ) + self.snapshotState = self.current.state.Copy() +} + func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsByPriceAndNonce, bc *core.BlockChain, coinbase common.Address) { gp := new(core.GasPool).AddGas(env.header.GasLimit)