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 (
"fmt"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
@ -19,12 +21,14 @@ type ExecTask interface {
MVReadList() []ReadDescriptor
MVWriteList() []WriteDescriptor
MVFullWriteList() []WriteDescriptor
Sender() common.Address
}
type ExecVersionView struct {
ver Version
et ExecTask
mvh *MVHashMap
ver Version
et ExecTask
mvh *MVHashMap
sender common.Address
}
func (ev *ExecVersionView) Execute() (er ExecResult) {
@ -55,6 +59,13 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
chTasks := make(chan ExecVersionView, len(tasks))
chResults := make(chan ExecResult, len(tasks))
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
@ -65,8 +76,15 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
select {
case task := <-t:
{
res := task.Execute()
chResults <- res
m := mutMap[task.sender]
if !m.TryLock() {
// why not this? -> chTasks <- task
t <- task
} else {
res := task.Execute()
chResults <- res
m.Unlock()
}
}
case <-chDone:
break Loop
@ -88,7 +106,7 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
cntExec++
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()
if nextTx != -1 {
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 ...
@ -221,7 +239,7 @@ func ExecuteParallel(tasks []ExecTask) (lastTxIO *TxnInputOutput, err error) {
cntExec++
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
shouldDelayFeeCal *bool
shouldRerunWithoutFeeDelay bool
sender common.Address
}
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()
}
func (task *ExecutionTask) Sender() common.Address {
return task.sender
}
// 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 processor (coinbase) and any included uncles.
@ -182,6 +187,7 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
blockContext: bc,
evmConfig: cfg,
shouldDelayFeeCal: &shouldDelayFeeCal,
sender: msg.From(),
}
tasks = append(tasks, task)