added 2 flags to enable parallel EVM and set the number of speculative processes (#727)

This commit is contained in:
Pratik Patil 2023-02-09 13:34:06 +05:30 committed by GitHub
parent d25aa76447
commit 9795a287d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 85 additions and 16 deletions

View file

@ -136,3 +136,7 @@ syncmode = "full"
# [developer]
# dev = false
# period = 0
# [parallelevm]
# enable = false
# procs = 8

View file

@ -2081,6 +2081,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
// TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only.
// Disable transaction indexing/unindexing by default.
// PSP - Check for config.ParallelEVM.Enable here?
chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil, nil)
if err != nil {
Fatalf("Can't create BlockChain: %v", err)

View file

@ -36,6 +36,12 @@ type ExecVersionView struct {
sender common.Address
}
var NumSpeculativeProcs int = 8
func SetProcs(specProcs int) {
NumSpeculativeProcs = specProcs
}
func (ev *ExecVersionView) Execute() (er ExecResult) {
er.ver = ev.ver
if er.err = ev.et.Execute(ev.mvh, ev.ver.Incarnation); er.err != nil {
@ -157,8 +163,7 @@ type ParallelExecutionResult struct {
AllDeps map[int]map[int]bool
}
const numGoProcs = 2
const numSpeculativeProcs = 8
const numGoProcs = 1
type ParallelExecutor struct {
tasks []ExecTask
@ -315,10 +320,10 @@ func (pe *ParallelExecutor) Prepare() {
}
}
pe.workerWg.Add(numSpeculativeProcs + numGoProcs)
pe.workerWg.Add(NumSpeculativeProcs + numGoProcs)
// Launch workers that execute transactions
for i := 0; i < numSpeculativeProcs+numGoProcs; i++ {
for i := 0; i < NumSpeculativeProcs+numGoProcs; i++ {
go func(procNum int) {
defer pe.workerWg.Done()
@ -352,7 +357,7 @@ func (pe *ParallelExecutor) Prepare() {
}
}
if procNum < numSpeculativeProcs {
if procNum < NumSpeculativeProcs {
for range pe.chSpeculativeTasks {
doWork(pe.specTaskQueue.Pop().(ExecVersionView))
}

View file

@ -34,6 +34,11 @@ import (
"github.com/ethereum/go-ethereum/params"
)
type ParallelEVMConfig struct {
Enable bool
SpeculativeProcesses int
}
// StateProcessor is a basic Processor, which takes care of transitioning
// state from one point to another.
//
@ -269,6 +274,8 @@ var parallelizabilityTimer = metrics.NewRegisteredTimer("block/parallelizability
// transactions failed to execute due to insufficient gas it will return an error.
// nolint:gocognit
func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
blockstm.SetProcs(cfg.ParallelSpeculativeProcesses)
var (
receipts types.Receipts
header = block.Header()

View file

@ -34,6 +34,10 @@ type Config struct {
JumpTable *JumpTable // EVM instruction table, automatically populated if unset
ExtraEips []int // Additional EIPS that are to be enabled
// parallel EVM configs
ParallelEnable bool
ParallelSpeculativeProcesses int
}
// ScopeContext contains the things that are per-call, such as stack and memory,

View file

@ -143,4 +143,8 @@ addr = ":3131"
[developer]
dev = false
period = 0
[blockstm]
enable = false
procs = 8
```

View file

@ -108,6 +108,7 @@ type Ethereum struct {
shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully
}
// PSP
// New creates a new Ethereum object (including the
// initialisation of the common Ethereum object)
func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
@ -206,7 +207,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}
var (
vmConfig = vm.Config{
EnablePreimageRecording: config.EnablePreimageRecording,
EnablePreimageRecording: config.EnablePreimageRecording,
ParallelEnable: config.ParallelEVM.Enable,
ParallelSpeculativeProcesses: config.ParallelEVM.SpeculativeProcesses,
}
cacheConfig = &core.CacheConfig{
TrieCleanLimit: config.TrieCleanCache,
@ -224,7 +227,14 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
checker := whitelist.NewService(10)
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, checker)
// check if Parallel EVM is enabled
// if enabled, use parallel state processor
if config.ParallelEVM.Enable {
eth.blockchain, err = core.NewParallelBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, checker)
} else {
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, checker)
}
if err != nil {
return nil, err
}

View file

@ -224,6 +224,9 @@ type Config struct {
// Bor logs flag
BorLogs bool
// Parallel EVM (Block-STM) related config
ParallelEVM core.ParallelEVMConfig `toml:",omitempty"`
// Arrow Glacier block override (TODO: remove after the fork)
OverrideArrowGlacier *big.Int `toml:",omitempty"`

View file

@ -104,6 +104,9 @@ type Config struct {
// Developer has the developer mode related settings
Developer *DeveloperConfig `hcl:"developer,block" toml:"developer,block"`
// ParallelEVM has the parallel evm related settings
ParallelEVM *ParallelEVMConfig `hcl:"parallelevm,block" toml:"parallelevm,block"`
}
type P2PConfig struct {
@ -398,6 +401,12 @@ type DeveloperConfig struct {
Period uint64 `hcl:"period,optional" toml:"period,optional"`
}
type ParallelEVMConfig struct {
Enable bool `hcl:"enable,optional" toml:"enable,optional"`
SpeculativeProcesses int `hcl:"procs,optional" toml:"procs,optional"`
}
func DefaultConfig() *Config {
return &Config{
Chain: "mainnet",
@ -531,6 +540,10 @@ func DefaultConfig() *Config {
Enabled: false,
Period: 0,
},
ParallelEVM: &ParallelEVMConfig{
Enable: false,
SpeculativeProcesses: 8,
},
}
}
@ -893,6 +906,9 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*
n.BorLogs = c.BorLogs
n.DatabaseHandles = dbHandles
n.ParallelEVM.Enable = c.ParallelEVM.Enable
n.ParallelEVM.SpeculativeProcesses = c.ParallelEVM.SpeculativeProcesses
return &n, nil
}

View file

@ -682,5 +682,19 @@ func (c *Command) Flags() *flagset.Flagset {
Value: &c.cliConfig.Developer.Period,
Default: c.cliConfig.Developer.Period,
})
// parallelevm
f.BoolFlag(&flagset.BoolFlag{
Name: "parallelevm.enable",
Usage: "Enable Block STM",
Value: &c.cliConfig.ParallelEVM.Enable,
Default: c.cliConfig.ParallelEVM.Enable,
})
f.IntFlag(&flagset.IntFlag{
Name: "parallelevm.procs",
Usage: "Number of speculative processes (cores) in Block STM",
Value: &c.cliConfig.ParallelEVM.SpeculativeProcesses,
Default: c.cliConfig.ParallelEVM.SpeculativeProcesses,
})
return f
}

View file

@ -756,7 +756,7 @@ func BenchmarkBorMiningBlockSTMMetadata(b *testing.B) {
db2 := rawdb.NewMemoryDatabase()
back.Genesis.MustCommit(db2)
chain, _ := core.NewParallelBlockChain(db2, nil, back.chain.Config(), engine, vm.Config{}, nil, nil, nil)
chain, _ := core.NewParallelBlockChain(db2, nil, back.chain.Config(), engine, vm.Config{ParallelEnable: true, ParallelSpeculativeProcesses: 8}, nil, nil, nil)
defer chain.Stop()
// Ignore empty commit here for less noise.

View file

@ -176,17 +176,18 @@ func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
}
}
/* See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
/*
See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
Whether a block is valid or not is a bit subtle, it's defined by presence of
blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
invalid and we must verify that we do not accept it.
Whether a block is valid or not is a bit subtle, it's defined by presence of
blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
invalid and we must verify that we do not accept it.
Since some tests mix valid and invalid blocks we need to check this for every block.
Since some tests mix valid and invalid blocks we need to check this for every block.
If a block is invalid it does not necessarily fail the test, if it's invalidness is
expected we are expected to ignore it and continue processing and then validate the
post state.
If a block is invalid it does not necessarily fail the test, if it's invalidness is
expected we are expected to ignore it and continue processing and then validate the
post state.
*/
func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
validBlocks := make([]btBlock, 0)