diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 2b1ea38483..6e7d28a0ce 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -198,6 +198,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // they are returned to the pools defer func() { returnStack(stack) + mem.Free() }() contract.Input = input diff --git a/core/vm/memory.go b/core/vm/memory.go index e0202fd7c0..e8263b1f16 100644 --- a/core/vm/memory.go +++ b/core/vm/memory.go @@ -17,9 +17,19 @@ package vm import ( + "sync" + "github.com/holiman/uint256" ) +var memoryPool = sync.Pool{ + New: func() any { + return &Memory{ + store: make([]byte, 0), + } + }, +} + // Memory implements a simple memory model for the ethereum virtual machine. type Memory struct { store []byte @@ -28,7 +38,18 @@ type Memory struct { // NewMemory returns a new memory model. func NewMemory() *Memory { - return &Memory{} + return memoryPool.Get().(*Memory) +} + +// Free returns the memory to the pool. +func (m *Memory) Free() { + // To reduce peak allocation, return only smaller memory instances to the pool. + const maxBufferSize = 16 << 10 + if cap(m.store) <= maxBufferSize { + m.store = m.store[:0] + m.lastGasCost = 0 + memoryPool.Put(m) + } } // Set sets offset + size to value