Txn prioritizer implemented using mutex map (#487)

* basic txn prioritizer implemented using mutex map

* Re-execute parallel tasks when there is a read in coinbase or burn address

* Re-execute parallel tasks when there is a read in coinbase or burn address

* using *sync.RWMutex{} in mutexMap

Co-authored-by: Jerry <jerrycgh@gmail.com>
This commit is contained in:
Pratik Patil 2022-08-19 10:32:55 +05:30 committed by Jerry
parent ab3ebebcca
commit f7bd7ca66b
2 changed files with 32 additions and 8 deletions

View file

@ -2,7 +2,9 @@ package blockstm
import ( import (
"fmt" "fmt"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
@ -19,12 +21,14 @@ type ExecTask interface {
MVReadList() []ReadDescriptor MVReadList() []ReadDescriptor
MVWriteList() []WriteDescriptor MVWriteList() []WriteDescriptor
MVFullWriteList() []WriteDescriptor MVFullWriteList() []WriteDescriptor
Sender() common.Address
} }
type ExecVersionView struct { type ExecVersionView struct {
ver Version ver Version
et ExecTask et ExecTask
mvh *MVHashMap mvh *MVHashMap
sender common.Address
} }
func (ev *ExecVersionView) Execute() (er ExecResult) { func (ev *ExecVersionView) Execute() (er ExecResult) {
@ -55,6 +59,13 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
chTasks := make(chan ExecVersionView, len(tasks)) chTasks := make(chan ExecVersionView, len(tasks))
chResults := make(chan ExecResult, len(tasks)) chResults := make(chan ExecResult, len(tasks))
chDone := make(chan bool) chDone := make(chan bool)
mutMap := map[common.Address]*sync.RWMutex{}
for _, t := range tasks {
if _, ok := mutMap[t.Sender()]; !ok {
mutMap[t.Sender()] = &sync.RWMutex{}
}
}
var cntExec, cntSuccess, cntAbort, cntTotalValidations, cntValidationFail int var cntExec, cntSuccess, cntAbort, cntTotalValidations, cntValidationFail int
@ -65,8 +76,15 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
select { select {
case task := <-t: case task := <-t:
{ {
res := task.Execute() m := mutMap[task.sender]
chResults <- res if !m.TryLock() {
// why not this? -> chTasks <- task
t <- task
} else {
res := task.Execute()
chResults <- res
m.Unlock()
}
} }
case <-chDone: case <-chDone:
break Loop break Loop
@ -88,7 +106,7 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
cntExec++ cntExec++
log.Debug("blockstm", "bootstrap: proc", x, "executing task", tx) log.Debug("blockstm", "bootstrap: proc", x, "executing task", tx)
chTasks <- ExecVersionView{ver: Version{tx, 0}, et: tasks[tx], mvh: mvh} chTasks <- ExecVersionView{ver: Version{tx, 0}, et: tasks[tx], mvh: mvh, sender: tasks[tx].Sender()}
} }
} }
@ -161,7 +179,7 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
nextTx := execTasks.takeNextPending() nextTx := execTasks.takeNextPending()
if nextTx != -1 { if nextTx != -1 {
cntExec++ cntExec++
chTasks <- ExecVersionView{ver: Version{nextTx, txIncarnations[nextTx]}, et: tasks[nextTx], mvh: mvh} chTasks <- ExecVersionView{ver: Version{nextTx, txIncarnations[nextTx]}, et: tasks[nextTx], mvh: mvh, sender: tasks[nextTx].Sender()}
} }
// do validations ... // do validations ...
@ -221,7 +239,7 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
cntExec++ cntExec++
log.Debug("blockstm", "# tx queued up", nextTx) log.Debug("blockstm", "# tx queued up", nextTx)
chTasks <- ExecVersionView{ver: Version{nextTx, txIncarnations[nextTx]}, et: tasks[nextTx], mvh: mvh} chTasks <- ExecVersionView{ver: Version{nextTx, txIncarnations[nextTx]}, et: tasks[nextTx], mvh: mvh, sender: tasks[nextTx].Sender()}
} }
} }

View file

@ -67,6 +67,7 @@ type ExecutionTask struct {
result *ExecutionResult result *ExecutionResult
shouldDelayFeeCal *bool shouldDelayFeeCal *bool
shouldRerunWithoutFeeDelay bool shouldRerunWithoutFeeDelay bool
sender common.Address
} }
func (task *ExecutionTask) Execute(mvh *blockstm.MVHashMap, incarnation int) (err error) { func (task *ExecutionTask) Execute(mvh *blockstm.MVHashMap, incarnation int) (err error) {
@ -129,6 +130,10 @@ func (task *ExecutionTask) MVFullWriteList() []blockstm.WriteDescriptor {
return task.statedb.MVFullWriteList() return task.statedb.MVFullWriteList()
} }
func (task *ExecutionTask) Sender() common.Address {
return task.sender
}
// Process processes the state changes according to the Ethereum rules by running // Process processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb and applying any rewards to both // the transaction messages using the statedb and applying any rewards to both
// the processor (coinbase) and any included uncles. // the processor (coinbase) and any included uncles.
@ -182,6 +187,7 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
blockContext: bc, blockContext: bc,
evmConfig: cfg, evmConfig: cfg,
shouldDelayFeeCal: &shouldDelayFeeCal, shouldDelayFeeCal: &shouldDelayFeeCal,
sender: msg.From(),
} }
tasks = append(tasks, task) tasks = append(tasks, task)