From 1201e7c4f83005f68ffbc65286e158e525b65f09 Mon Sep 17 00:00:00 2001 From: Austin Roberts Date: Fri, 7 Jan 2022 11:34:07 -0600 Subject: [PATCH 1/3] Avoid unnecessary RLP encoding While looking for the source of a memory leak, I decided to optimize the metatracer to avoid encoding values when there weren't any tracers configured to received the encoded values. I also avoided putting the EVM into debug mode when there weren't any tracers configured. None of these fixed the memory leak, but they still seem like good practices. Memory leak fix is in the next commit. --- core/plugin_hooks.go | 11 ++++++++--- core/state_processor.go | 8 +++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/core/plugin_hooks.go b/core/plugin_hooks.go index 77a5643ed..5ddde7437 100644 --- a/core/plugin_hooks.go +++ b/core/plugin_hooks.go @@ -190,6 +190,7 @@ type metaTracer struct { } func (mt *metaTracer) PreProcessBlock(block *types.Block) { + if len(mt.tracers) == 0 { return } blockHash := core.Hash(block.Hash()) blockNumber := block.NumberU64() encoded, _ := rlp.EncodeToBytes(block) @@ -198,6 +199,7 @@ func (mt *metaTracer) PreProcessBlock(block *types.Block) { } } func (mt *metaTracer) PreProcessTransaction(tx *types.Transaction, block *types.Block, i int) { + if len(mt.tracers) == 0 { return } blockHash := core.Hash(block.Hash()) transactionHash := core.Hash(tx.Hash()) for _, tracer := range mt.tracers { @@ -205,6 +207,7 @@ func (mt *metaTracer) PreProcessTransaction(tx *types.Transaction, block *types. } } func (mt *metaTracer) BlockProcessingError(tx *types.Transaction, block *types.Block, err error) { + if len(mt.tracers) == 0 { return } blockHash := core.Hash(block.Hash()) transactionHash := core.Hash(tx.Hash()) for _, tracer := range mt.tracers { @@ -212,6 +215,7 @@ func (mt *metaTracer) BlockProcessingError(tx *types.Transaction, block *types.B } } func (mt *metaTracer) PostProcessTransaction(tx *types.Transaction, block *types.Block, i int, receipt *types.Receipt) { + if len(mt.tracers) == 0 { return } blockHash := core.Hash(block.Hash()) transactionHash := core.Hash(tx.Hash()) receiptBytes, _ := json.Marshal(receipt) @@ -220,6 +224,7 @@ func (mt *metaTracer) PostProcessTransaction(tx *types.Transaction, block *types } } func (mt *metaTracer) PostProcessBlock(block *types.Block) { + if len(mt.tracers) == 0 { return } blockHash := core.Hash(block.Hash()) for _, tracer := range mt.tracers { tracer.PostProcessBlock(blockHash) @@ -258,7 +263,7 @@ func (mt *metaTracer) CaptureExit(output []byte, gasUsed uint64, err error) { } } -func PluginGetBlockTracer(pl *plugins.PluginLoader, hash common.Hash, statedb *state.StateDB) *metaTracer { +func PluginGetBlockTracer(pl *plugins.PluginLoader, hash common.Hash, statedb *state.StateDB) (*metaTracer, bool) { //look for a function that takes whatever the ctx provides and statedb and returns a core.blocktracer append into meta tracer tracerList := plugins.Lookup("GetLiveTracer", func(item interface{}) bool { _, ok := item.(func(core.Hash, core.StateDB) core.BlockTracer) @@ -274,9 +279,9 @@ func PluginGetBlockTracer(pl *plugins.PluginLoader, hash common.Hash, statedb *s } } } - return mt + return mt, (len(mt.tracers) > 0) } -func pluginGetBlockTracer(hash common.Hash, statedb *state.StateDB) *metaTracer { +func pluginGetBlockTracer(hash common.Hash, statedb *state.StateDB) (*metaTracer, bool) { if plugins.DefaultPluginLoader == nil { log.Warn("Attempting GetBlockTracer, but default PluginLoader has not been initialized") return &metaTracer{} diff --git a/core/state_processor.go b/core/state_processor.go index 273815fae..a7903cb96 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -71,9 +71,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg misc.ApplyDAOHardFork(statedb) } blockContext := NewEVMBlockContext(header, p.bc, nil) - blockTracer := pluginGetBlockTracer(header.Hash(), statedb) - cfg.Tracer = blockTracer - cfg.Debug = true + blockTracer, ok := pluginGetBlockTracer(header.Hash(), statedb) + if ok { + cfg.Tracer = blockTracer + cfg.Debug = true + } vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) // Iterate over and process the individual transactions pluginPreProcessBlock(block) From 9f28e94d66a28beb6e6000a095b001c8ed146818 Mon Sep 17 00:00:00 2001 From: Austin Roberts Date: Fri, 7 Jan 2022 11:36:30 -0600 Subject: [PATCH 2/3] Fix memory leak in freezer implementation It turns out we were only notifying plugins of freezer commits and cleaning up our record when the block being processed was greater than MAX_UINT64. So, uh, never. --- core/rawdb/plugin_hooks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rawdb/plugin_hooks.go b/core/rawdb/plugin_hooks.go index 1845408cb..3de55cc40 100644 --- a/core/rawdb/plugin_hooks.go +++ b/core/rawdb/plugin_hooks.go @@ -39,7 +39,7 @@ func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) { if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) } min := ^uint64(0) for i := range freezerUpdates{ - if min < i { min = i } + if min > i { min = i } } for i := min ; i < num; i++ { update, ok := freezerUpdates[i] From a88d316b0a4adc46adc8efc7ddee5377006aa6db Mon Sep 17 00:00:00 2001 From: Austin Roberts Date: Fri, 7 Jan 2022 12:05:18 -0600 Subject: [PATCH 3/3] Fix missing return value --- core/plugin_hooks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/plugin_hooks.go b/core/plugin_hooks.go index 5ddde7437..e1a2544bb 100644 --- a/core/plugin_hooks.go +++ b/core/plugin_hooks.go @@ -284,7 +284,7 @@ func PluginGetBlockTracer(pl *plugins.PluginLoader, hash common.Hash, statedb *s func pluginGetBlockTracer(hash common.Hash, statedb *state.StateDB) (*metaTracer, bool) { if plugins.DefaultPluginLoader == nil { log.Warn("Attempting GetBlockTracer, but default PluginLoader has not been initialized") - return &metaTracer{} + return &metaTracer{}, false } return PluginGetBlockTracer(plugins.DefaultPluginLoader, hash, statedb) }