Skip to content

Commit

Permalink
no once
Browse files Browse the repository at this point in the history
  • Loading branch information
sunny2022da committed Mar 13, 2024
1 parent cd76692 commit a3530dc
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 81 deletions.
3 changes: 2 additions & 1 deletion cmd/evm/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
compiler2 "github.com/ethereum/go-ethereum/core/opcodeCompiler/compiler"
"io"
"math/big"
Expand Down Expand Up @@ -221,7 +222,7 @@ func runCmd(ctx *cli.Context) error {
}

if runtimeConfig.EVMConfig.EnableOpcodeOptimizations {
compiler2.GetOpcodeProcessorInstance().EnableOptimization()
compiler2.EnableOptimization()
}
if cpuProfilePath := ctx.String(CPUProfileFlag.Name); cpuProfilePath != "" {
f, err := os.Create(cpuProfilePath)
Expand Down
4 changes: 2 additions & 2 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(VMOpcodeOptimizeFlag.Name) {
// TODO(fjl): force-enable this in --dev mode
cfg.EnableOpcodeOptimizing = ctx.Bool(VMOpcodeOptimizeFlag.Name)
compiler.GetOpcodeProcessorInstance().EnableOptimization()
compiler.EnableOptimization()
}

if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
Expand Down Expand Up @@ -2376,7 +2376,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
EnableOpcodeOptimizations: ctx.Bool(VMOpcodeOptimizeFlag.Name)}

if vmcfg.EnableOpcodeOptimizations {
compiler.GetOpcodeProcessorInstance()
compiler.EnableOptimization()
}
// Disable transaction indexing/unindexing by default.
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil)
Expand Down
66 changes: 37 additions & 29 deletions core/opcodeCompiler/compiler/OpCodeCache.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,21 @@ type OpCodeCache struct {
codeCacheSize uint64
}

func (c *OpCodeCache) GetCachedCode(address common.Address) OptCode {
func (c *OpCodeCache) RemoveCachedCode(address common.Address) {
c.codeCacheMutex.Lock()
if c.opcodesCache == nil || c.codeCacheSize == 0 {
c.codeCacheMutex.Unlock()
return
}
_, ok := c.opcodesCache[address]
if ok {
delete(c.opcodesCache, address)
}
c.codeCacheMutex.Unlock()
}

func (c *OpCodeCache) GetCachedCode(address common.Address) OptCode {
c.codeCacheMutex.RLock()

processedCode, ok := c.opcodesCache[address]
if !ok {
processedCode = nil
Expand Down Expand Up @@ -57,34 +68,35 @@ func (c *OpCodeCache) UpdateCodeCache(address common.Address, code OptCode) erro
return nil
}

var once sync.Once
var opcodeCache *OpCodeCache

const codeCacheFileName = "codecache.json"

func getOpCodeCacheInstance() *OpCodeCache {
once.Do(func() {
opcodeCache = &OpCodeCache{
opcodesCache: make(map[common.Address]OptCode, CodeCacheGCThreshold>>10),
codeCacheMutex: sync.RWMutex{},
}
// Try load code cache
loadCodeCacheFromFile(codeCacheFileName, opcodeCache)
// Handle Sigusr2 signal
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGUSR2)
go func() {
for { // Infinite loop to wait for signals
signal := <-sigCh
switch signal {
case syscall.SIGUSR2:
opcodeCache.codeCacheMutex.RLock()
dumpCodeCache(codeCacheFileName, opcodeCache.opcodesCache)
opcodeCache.codeCacheMutex.RUnlock()
}
func init() {
opcodeCache = &OpCodeCache{
opcodesCache: make(map[common.Address]OptCode, CodeCacheGCThreshold>>10),
codeCacheMutex: sync.RWMutex{},
}

// Try load code cache
loadCodeCacheFromFile(codeCacheFileName, opcodeCache)
// Handle Sigusr2 signal
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGUSR2)
go func() {
for { // Infinite loop to wait for signals
signal := <-sigCh
switch signal {
case syscall.SIGUSR2:
opcodeCache.codeCacheMutex.RLock()
dumpCodeCache(codeCacheFileName, opcodeCache.opcodesCache)
opcodeCache.codeCacheMutex.RUnlock()
}
}()
})
}
}()
}

func getOpCodeCacheInstance() *OpCodeCache {
return opcodeCache
}

Expand All @@ -97,10 +109,6 @@ func dumpCodeCache(filename string, codeCache map[common.Address]OptCode) {
return
}

// Print JSON to standard output
//fmt.Println("Data JSON:")
// fmt.Println(string(jsonData))

log.Info("OpcodeCache Dump:", "File", filename)
// Optional: write JSON to file
err = writeToFile(filename, jsonData)
Expand Down
104 changes: 61 additions & 43 deletions core/opcodeCompiler/compiler/opcodeProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256"
"runtime"
"sync"
)

type CodeType uint8

var ErrFailPreprocessing = errors.New("fail to do preprocessing")
var ErrOptiDisabled = errors.New("Opcode optimization is disabled")

var initOnce sync.Once
var opcodeProcessor *OpcodeProcessor
var opCodeOptimizationInited bool

const taskChannelSize = 1024 * 1024

type OpcodeProcessor struct {
var (
enabled bool
codeCache *OpCodeCache
taskChannel chan optimizeTask
}
)

type OpCodeProcessorConfig struct {
DoOpcodeFusion bool
Expand All @@ -43,104 +41,124 @@ type optimizeTask struct {
rawCode []byte
}

func GetOpcodeProcessorInstance() *OpcodeProcessor {
initOnce.Do(func() {
opcodeProcessor = &OpcodeProcessor{
enabled: false,
codeCache: nil,
taskChannel: make(chan optimizeTask, taskChannelSize),
}
// start task processors.
taskNumber := max(runtime.NumCPU()*3/8, 1)

for i := 0; i < taskNumber; i++ {
go opcodeProcessor.taskProcessor()
}
})
return opcodeProcessor
func init() {
if opCodeOptimizationInited {
return
}
opCodeOptimizationInited = true
enabled = false
codeCache = nil
taskChannel = make(chan optimizeTask, taskChannelSize)
// start task processors.
taskNumber := max(runtime.NumCPU()*3/8, 1)
codeCache = getOpCodeCacheInstance()

for i := 0; i < taskNumber; i++ {
go taskProcessor()
}
}

func (p *OpcodeProcessor) EnableOptimization() {
if p.enabled {
func EnableOptimization() {
if enabled {
return
}
p.enabled = true
p.codeCache = getOpCodeCacheInstance()
enabled = true
}

func (p *OpcodeProcessor) DisableOptimization() {
p.enabled = false
func DisableOptimization() {
enabled = false
}

// Producer functions
func (p *OpcodeProcessor) LoadOptimizedCode(address common.Address) OptCode {
if !p.enabled {
func LoadOptimizedCode(address common.Address) OptCode {
if !enabled {
return nil
}
/* Try load from cache */
codeCache := p.codeCache
processedCode := codeCache.GetCachedCode(address)
return processedCode

}

func (p *OpcodeProcessor) GenOrLoadOptimizedCode(address common.Address, code []byte) {
func GenOrLoadOptimizedCode(address common.Address, code []byte) {
task := optimizeTask{generate, address, code}
p.taskChannel <- task
taskChannel <- task
}

func FlushCodeCache(address common.Address) {
task := optimizeTask{flush, address, nil}
taskChannel <- task
}

func RewriteOptimizedCodeForDB(address common.Address, code []byte, hash common.Hash) {
if enabled {
// p.GenOrRewriteOptimizedCode(address, code, hash)
//
GenOrLoadOptimizedCode(address, code)
}
}

// Consumer function
func (p *OpcodeProcessor) taskProcessor() {
func taskProcessor() {
for {
task := <-p.taskChannel
task := <-taskChannel
// Process the message here
p.handleOptimizationTask(task)
handleOptimizationTask(task)
}
}

func (p *OpcodeProcessor) handleOptimizationTask(task optimizeTask) {
func handleOptimizationTask(task optimizeTask) {
switch task.taskType {
case generate:
p.TryGenerateOptimizedCode(task.addr, task.rawCode)
TryGenerateOptimizedCode(task.addr, task.rawCode)
case flush:
DeleteCodeCache(task.addr)
}
}

// GenOrRewriteOptimizedCode generate the optimized code and refresh the codecache.
func (p *OpcodeProcessor) GenOrRewriteOptimizedCode(address common.Address, code []byte) (OptCode, error) {
if !p.enabled {
func GenOrRewriteOptimizedCode(address common.Address, code []byte) (OptCode, error) {
if !enabled {
return nil, ErrOptiDisabled
}
processedCode, err := processByteCodes(code)
if err != nil {
log.Error("Can not generate optimized code: %s\n", err.Error())
return nil, err
}
codeCache := p.codeCache

err = codeCache.UpdateCodeCache(address, processedCode)
if err != nil {
log.Error("Not update code cache", "err", err)
}
return processedCode, err
}

func (p *OpcodeProcessor) TryGenerateOptimizedCode(address common.Address, code []byte) (OptCode, bool, error) {
if !p.enabled {
func TryGenerateOptimizedCode(address common.Address, code []byte) (OptCode, bool, error) {
if !enabled {
return nil, false, ErrOptiDisabled
}
/* Try load from cache */
codeCache := p.codeCache
processedCode := codeCache.GetCachedCode(address)
hit := false
var err error = nil
if processedCode == nil || len(processedCode) == 0 {
processedCode, err = p.GenOrRewriteOptimizedCode(address, code)
processedCode, err = GenOrRewriteOptimizedCode(address, code)
hit = false
} else {
hit = true
}
return processedCode, hit, err
}

func DeleteCodeCache(addr common.Address) {
if enabled {
return
}
// flush in case there are invalid cached code
codeCache.RemoveCachedCode(addr)
}

func processByteCodes(code []byte) (OptCode, error) {
return doOpcodesProcess(code)
}
Expand Down
6 changes: 3 additions & 3 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
evm.depth = 0
evm.interpreter = NewEVMInterpreter(evm)
if config.EnableOpcodeOptimizations {
compiler.GetOpcodeProcessorInstance().EnableOptimization()
compiler.EnableOptimization()
}
return evm
}
Expand Down Expand Up @@ -448,12 +448,12 @@ func tryGetOptimizedCode(evm *EVM, addrCopy common.Address) (bool, []byte) {
}
optimized := false
if evm.Config.EnableOpcodeOptimizations {
optCode := compiler.GetOpcodeProcessorInstance().LoadOptimizedCode(addrCopy)
optCode := compiler.LoadOptimizedCode(addrCopy)
if len(optCode) != 0 {
code = optCode
optimized = true
} else {
compiler.GetOpcodeProcessorInstance().GenOrLoadOptimizedCode(addrCopy, code)
compiler.GenOrLoadOptimizedCode(addrCopy, code)
}
}
return optimized, code
Expand Down
4 changes: 2 additions & 2 deletions core/vm/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ func TestRuntimeJSTracerWithOpcodeOptimizer(t *testing.T) {
byte(vm.SELFDESTRUCT),
}
main := common.HexToAddress("0xaa")
compiler.GetOpcodeProcessorInstance().EnableOptimization()
compiler.EnableOptimization()
for i, jsTracer := range jsTracers {
for j, tc := range tests {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
Expand All @@ -1023,7 +1023,7 @@ func TestRuntimeJSTracerWithOpcodeOptimizer(t *testing.T) {
Tracer: tracer,
EnableOpcodeOptimizations: true,
}})
compiler.GetOpcodeProcessorInstance().DeleteCodeCache(main, common.Hash{})
compiler.DeleteCodeCache(main)
if err != nil {
t.Fatal("didn't expect error", err)
}
Expand Down
4 changes: 3 additions & 1 deletion eth/tracers/js/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ func runTraceWithOption(tracer tracers.Tracer, vmctx *vmContext, chaincfg *param
}

if enableOpti {
optimized, _ := compiler.GetOpcodeProcessorInstance().GenOrRewriteOptimizedCode(contract.Address(), contract.Code)
// reset the code also require flush code cache.
compiler.DeleteCodeCache(contract.Address())
optimized, _ := compiler.GenOrRewriteOptimizedCode(contract.Address(), contract.Code)
contract.Code = optimized
}

Expand Down

0 comments on commit a3530dc

Please sign in to comment.