miner: filter duplicate sealing work

This commit is contained in:
rjl493456442 2018-08-21 12:31:16 +08:00
parent d08db95664
commit f6caea46db

View file

@ -156,6 +156,7 @@ type worker struct {
// atomic status counters // atomic status counters
running int32 // The indicator whether the consensus engine is running or not. running int32 // The indicator whether the consensus engine is running or not.
newTxs int32 // New arrival transaction count since last sealing work submitting.
// Test hooks // Test hooks
newTaskHook func(*task) // Method to call upon receiving a new sealing task. newTaskHook func(*task) // Method to call upon receiving a new sealing task.
@ -293,6 +294,7 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
interrupt = new(int32) interrupt = new(int32)
w.newWorkCh <- &newWorkReq{interrupt: interrupt, noempty: noempty} w.newWorkCh <- &newWorkReq{interrupt: interrupt, noempty: noempty}
timer.Reset(recommit) timer.Reset(recommit)
atomic.StoreInt32(&w.newTxs, 0)
} }
// recalcRecommit recalculates the resubmitting interval upon feedback. // recalcRecommit recalculates the resubmitting interval upon feedback.
recalcRecommit := func(target float64, inc bool) { recalcRecommit := func(target float64, inc bool) {
@ -332,6 +334,11 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
// If mining is running resubmit a new work cycle periodically to pull in // If mining is running resubmit a new work cycle periodically to pull in
// higher priced transactions. Disable this overhead for pending blocks. // higher priced transactions. Disable this overhead for pending blocks.
if w.isRunning() && (w.config.Clique == nil || w.config.Clique.Period > 0) { if w.isRunning() && (w.config.Clique == nil || w.config.Clique.Period > 0) {
// Short circuit if no new transaction arrives.
if atomic.LoadInt32(&w.newTxs) == 0 {
timer.Reset(recommit)
continue
}
commit(true, commitInterruptResubmit) commit(true, commitInterruptResubmit)
} }
@ -434,6 +441,7 @@ func (w *worker) mainLoop() {
w.commitNewWork(nil, false) w.commitNewWork(nil, false)
} }
} }
atomic.AddInt32(&w.newTxs, int32(len(ev.Txs)))
// System stopped // System stopped
case <-w.exitCh: case <-w.exitCh:
@ -478,7 +486,10 @@ func (w *worker) seal(t *task, stop <-chan struct{}) {
// taskLoop is a standalone goroutine to fetch sealing task from the generator and // taskLoop is a standalone goroutine to fetch sealing task from the generator and
// push them to consensus engine. // push them to consensus engine.
func (w *worker) taskLoop() { func (w *worker) taskLoop() {
var stopCh chan struct{} var (
stopCh chan struct{}
prev common.Hash
)
// interrupt aborts the in-flight sealing task. // interrupt aborts the in-flight sealing task.
interrupt := func() { interrupt := func() {
@ -493,8 +504,13 @@ func (w *worker) taskLoop() {
if w.newTaskHook != nil { if w.newTaskHook != nil {
w.newTaskHook(task) w.newTaskHook(task)
} }
// Reject duplicate sealing work due to resubmitting.
if task.block.HashNoNonce() == prev {
continue
}
interrupt() interrupt()
stopCh = make(chan struct{}) stopCh = make(chan struct{})
prev = task.block.HashNoNonce()
go w.seal(task, stopCh) go w.seal(task, stopCh)
case <-w.exitCh: case <-w.exitCh:
interrupt() interrupt()
@ -509,11 +525,15 @@ func (w *worker) resultLoop() {
for { for {
select { select {
case result := <-w.resultCh: case result := <-w.resultCh:
// Short circuit when receiving empty result.
if result == nil { if result == nil {
continue continue
} }
// Short circuit when receiving duplicate result caused by resubmitting.
block := result.block block := result.block
if w.chain.HasBlock(block.Hash(), block.NumberU64()) {
continue
}
// Update the block hash in all logs since it is now available and not when the // Update the block hash in all logs since it is now available and not when the
// receipt/log of individual transactions were created. // receipt/log of individual transactions were created.
for _, r := range result.receipts { for _, r := range result.receipts {