Skip to content

Commit

Permalink
Reapply "refactor: reduce number of heap allocations in tracing (#952)…
Browse files Browse the repository at this point in the history
…" (#959)

This reverts commit 2ba5ea3.
  • Loading branch information
omerfirmak committed Aug 21, 2024
1 parent c14f5c3 commit 346dd85
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 40 deletions.
6 changes: 3 additions & 3 deletions core/types/l2trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type ExecutionResult struct {
// currently they are just `from` and `to` account
AccountsAfter []*AccountWrapper `json:"accountAfter"`

StructLogs []*StructLogRes `json:"structLogs"`
StructLogs []StructLogRes `json:"structLogs"`
CallTrace json.RawMessage `json:"callTrace"`
}

Expand All @@ -91,8 +91,8 @@ type StructLogRes struct {

// NewStructLogResBasic Basic StructLogRes skeleton, Stack&Memory&Storage&ExtraData are separated from it for GC optimization;
// still need to fill in with Stack&Memory&Storage&ExtraData
func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int, refundCounter uint64, err error) *StructLogRes {
logRes := &StructLogRes{
func NewStructLogResBasic(pc uint64, op string, gas, gasCost uint64, depth int, refundCounter uint64, err error) StructLogRes {
logRes := StructLogRes{
Pc: pc,
Op: op,
Gas: gas,
Expand Down
62 changes: 34 additions & 28 deletions core/vm/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"io"
"math/big"
"strings"
"sync"
"time"

"github.com/holiman/uint256"
Expand Down Expand Up @@ -79,8 +80,8 @@ type StructLog struct {
Err error `json:"-"`
}

func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error) *StructLog {
return &StructLog{
func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error) StructLog {
return StructLog{
Pc: pc,
Op: op,
Gas: gas,
Expand All @@ -90,14 +91,6 @@ func NewStructlog(pc uint64, op OpCode, gas, cost uint64, depth int, err error)
}
}

func (s *StructLog) clean() {
s.Memory.Reset()
s.Stack = s.Stack[:0]
s.ReturnData.Reset()
s.Storage = nil
s.Err = nil
}

// overrides for gencodec
type structLogMarshaling struct {
Gas math.HexOrDecimal64
Expand Down Expand Up @@ -158,10 +151,11 @@ type StructLogger struct {
storage map[common.Address]Storage
createdAccount *types.AccountWrapper

callStackLogInd []int
logs []*StructLog
output []byte
err error
callStackLogInd []int
pooledLogSliceHeader *[]StructLog
logs []StructLog
output []byte
err error
}

// NewStructLogger returns a new logger
Expand All @@ -178,16 +172,26 @@ func NewStructLogger(cfg *LogConfig) *StructLogger {
return logger
}

// Reset clears the data held by the logger.
func (l *StructLogger) Reset() {
l.bytecodes = make(map[common.Hash]CodeInfo)
l.storage = make(map[common.Address]Storage)
l.statesAffected = make(map[common.Address]struct{})
l.output = make([]byte, 0)
l.logs = l.logs[:0]
l.callStackLogInd = nil
l.err = nil
l.createdAccount = nil
var logsPool = sync.Pool{
New: func() any {
return new([]StructLog)
},
}

// InitLogsFromPool initiliazes logs buffer from a pool instead of unconditionally allocating
// a new buffer every time
func (l *StructLogger) InitLogsFromPool() {
l.pooledLogSliceHeader = logsPool.Get().(*[]StructLog)
l.logs = *l.pooledLogSliceHeader
}

// ReleaseLogsToPool releases the logs back to the pool
// Keep in mind after calling this any copies of the internal StructLog buffer that you may
// have acquired by calling StructLogs() is invalid. Do not interact with it in any way.
func (l *StructLogger) ReleaseLogsToPool() {
*l.pooledLogSliceHeader = l.logs[:0]
l.logs = nil
logsPool.Put(l.pooledLogSliceHeader)
}

// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
Expand Down Expand Up @@ -359,7 +363,7 @@ func (l *StructLogger) TracedBytecodes() map[common.Hash]CodeInfo {
func (l *StructLogger) CreatedAccount() *types.AccountWrapper { return l.createdAccount }

// StructLogs returns the captured log entries.
func (l *StructLogger) StructLogs() []*StructLog { return l.logs }
func (l *StructLogger) StructLogs() []StructLog { return l.logs }

// Error returns the VM error captured by the trace.
func (l *StructLogger) Error() error { return l.err }
Expand All @@ -368,7 +372,7 @@ func (l *StructLogger) Error() error { return l.err }
func (l *StructLogger) Output() []byte { return l.output }

// WriteTrace writes a formatted trace to the given writer
func WriteTrace(writer io.Writer, logs []*StructLog) {
func WriteTrace(writer io.Writer, logs []StructLog) {
for _, log := range logs {
fmt.Fprintf(writer, "%-16spc=%08d gas=%v cost=%v", log.Op, log.Pc, log.Gas, log.GasCost)
if log.Err != nil {
Expand Down Expand Up @@ -488,9 +492,11 @@ func (t *mdLogger) CaptureEnter(typ OpCode, from common.Address, to common.Addre
func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}

// FormatLogs formats EVM returned structured logs for json output
func FormatLogs(logs []*StructLog) []*types.StructLogRes {
formatted := make([]*types.StructLogRes, 0, len(logs))
func FormatLogs(logs []StructLog) []types.StructLogRes {
formatted := make([]types.StructLogRes, 0, len(logs))

// note: make sure you don't retain a reference to any memory that originally belongs to `logs` as they might be pooled and
// reused
for _, trace := range logs {
logRes := types.NewStructLogResBasic(trace.Pc, trace.Op.String(), trace.Gas, trace.GasCost, trace.Depth, trace.RefundCounter, trace.Err)
for _, stackValue := range trace.Stack {
Expand Down
10 changes: 5 additions & 5 deletions eth/tracers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func TestTraceCall(t *testing.T) {
Gas: params.TxGas,
Failed: false,
ReturnValue: "",
StructLogs: []*types.StructLogRes{},
StructLogs: []types.StructLogRes{},
},
},
// Standard JSON trace upon the head, plain transfer.
Expand All @@ -245,7 +245,7 @@ func TestTraceCall(t *testing.T) {
Gas: params.TxGas,
Failed: false,
ReturnValue: "",
StructLogs: []*types.StructLogRes{},
StructLogs: []types.StructLogRes{},
},
},
// Standard JSON trace upon the non-existent block, error expects
Expand Down Expand Up @@ -275,7 +275,7 @@ func TestTraceCall(t *testing.T) {
Gas: params.TxGas,
Failed: false,
ReturnValue: "",
StructLogs: []*types.StructLogRes{},
StructLogs: []types.StructLogRes{},
},
},
// Standard JSON trace upon the pending block
Expand All @@ -293,7 +293,7 @@ func TestTraceCall(t *testing.T) {
Gas: params.TxGas,
Failed: false,
ReturnValue: "",
StructLogs: []*types.StructLogRes{},
StructLogs: []types.StructLogRes{},
},
},
}
Expand Down Expand Up @@ -347,7 +347,7 @@ func TestTraceTransaction(t *testing.T) {
Gas: params.TxGas,
Failed: false,
ReturnValue: "",
StructLogs: []*types.StructLogRes{},
StructLogs: []types.StructLogRes{},
}) {
t.Error("Transaction tracing result is different")
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ require (
github.com/rjeczalik/notify v0.9.1
github.com/rs/cors v1.7.0
github.com/scroll-tech/da-codec v0.1.1-0.20240718144756-1875fd490923
github.com/scroll-tech/zktrie v0.8.4
github.com/scroll-tech/zktrie v0.8.5-0.20240821080004-fe110072a0a1
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sourcegraph/conc v0.3.0
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,8 @@ github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scroll-tech/da-codec v0.1.1-0.20240718144756-1875fd490923 h1:A1ItzpnFDCHMh4g6cpeBZf7/fPf2lfwHbhjr/FSpk2w=
github.com/scroll-tech/da-codec v0.1.1-0.20240718144756-1875fd490923/go.mod h1:D6XEESeNVJkQJlv3eK+FyR+ufPkgVQbJzERylQi53Bs=
github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE=
github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/scroll-tech/zktrie v0.8.5-0.20240821080004-fe110072a0a1 h1:1WofmDyxxynpzfWkguUp2qAW4Dxaa0nYOrQ1tdYPYZU=
github.com/scroll-tech/zktrie v0.8.5-0.20240821080004-fe110072a0a1/go.mod h1:F5gbEGfKRMpjdTfaAnUHD51wfCmLnoSYokiJJpUtfBw=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
Expand Down
4 changes: 3 additions & 1 deletion rollup/tracing/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type TraceEnv struct {
// The following Mutexes are used to protect against parallel read/write,
// since txs are executed in parallel.
pMu sync.Mutex // for `TraceEnv.StorageTrace.Proofs`
sMu sync.Mutex // for `TraceEnv.state``
sMu sync.Mutex // for `TraceEnv.state`
cMu sync.Mutex // for `TraceEnv.Codes`

*types.StorageTrace
Expand Down Expand Up @@ -325,6 +325,8 @@ func (env *TraceEnv) getTxResult(state *state.StateDB, index int, block *types.B

applyMessageStart := time.Now()
structLogger := vm.NewStructLogger(env.logConfig)
structLogger.InitLogsFromPool()
defer structLogger.ReleaseLogsToPool()
tracer := NewMuxTracer(structLogger, callTracer)
// Run the transaction with tracing enabled.
vmenv := vm.NewEVM(env.blockCtx, txContext, state, env.chainConfig, vm.Config{Debug: true, Tracer: tracer, NoBaseFee: true})
Expand Down

0 comments on commit 346dd85

Please sign in to comment.