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] # [developer]
# dev = false # dev = false
# period = 0 # 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. // TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only.
// Disable transaction indexing/unindexing by default. // 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) chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil, nil)
if err != nil { if err != nil {
Fatalf("Can't create BlockChain: %v", err) Fatalf("Can't create BlockChain: %v", err)

View file

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

View file

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

View file

@ -34,6 +34,10 @@ type Config struct {
JumpTable *JumpTable // EVM instruction table, automatically populated if unset JumpTable *JumpTable // EVM instruction table, automatically populated if unset
ExtraEips []int // Additional EIPS that are to be enabled 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, // ScopeContext contains the things that are per-call, such as stack and memory,

View file

@ -143,4 +143,8 @@ addr = ":3131"
[developer] [developer]
dev = false dev = false
period = 0 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 shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully
} }
// PSP
// New creates a new Ethereum object (including the // New creates a new Ethereum object (including the
// initialisation of the common Ethereum object) // initialisation of the common Ethereum object)
func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
@ -207,6 +208,8 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
var ( var (
vmConfig = vm.Config{ vmConfig = vm.Config{
EnablePreimageRecording: config.EnablePreimageRecording, EnablePreimageRecording: config.EnablePreimageRecording,
ParallelEnable: config.ParallelEVM.Enable,
ParallelSpeculativeProcesses: config.ParallelEVM.SpeculativeProcesses,
} }
cacheConfig = &core.CacheConfig{ cacheConfig = &core.CacheConfig{
TrieCleanLimit: config.TrieCleanCache, TrieCleanLimit: config.TrieCleanCache,
@ -224,7 +227,14 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
checker := whitelist.NewService(10) checker := whitelist.NewService(10)
// 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) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit, checker)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

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

View file

@ -104,6 +104,9 @@ type Config struct {
// Developer has the developer mode related settings // Developer has the developer mode related settings
Developer *DeveloperConfig `hcl:"developer,block" toml:"developer,block"` 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 { type P2PConfig struct {
@ -398,6 +401,12 @@ type DeveloperConfig struct {
Period uint64 `hcl:"period,optional" toml:"period,optional"` 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 { func DefaultConfig() *Config {
return &Config{ return &Config{
Chain: "mainnet", Chain: "mainnet",
@ -531,6 +540,10 @@ func DefaultConfig() *Config {
Enabled: false, Enabled: false,
Period: 0, 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.BorLogs = c.BorLogs
n.DatabaseHandles = dbHandles n.DatabaseHandles = dbHandles
n.ParallelEVM.Enable = c.ParallelEVM.Enable
n.ParallelEVM.SpeculativeProcesses = c.ParallelEVM.SpeculativeProcesses
return &n, nil return &n, nil
} }

View file

@ -682,5 +682,19 @@ func (c *Command) Flags() *flagset.Flagset {
Value: &c.cliConfig.Developer.Period, Value: &c.cliConfig.Developer.Period,
Default: 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 return f
} }

View file

@ -756,7 +756,7 @@ func BenchmarkBorMiningBlockSTMMetadata(b *testing.B) {
db2 := rawdb.NewMemoryDatabase() db2 := rawdb.NewMemoryDatabase()
back.Genesis.MustCommit(db2) 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() defer chain.Stop()
// Ignore empty commit here for less noise. // Ignore empty commit here for less noise.

View file

@ -176,7 +176,8 @@ 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 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 blockHeader, transactions and uncleHeaders fields. If they are missing, the block is