From 799394192b9a9bf7e93f4511d1423b57e30929b1 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 3 Jun 2022 23:49:51 +0300 Subject: [PATCH] state: create buffer/io writer once per TokenTransferLog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta TokenTransferLog_Append-8 93.0µs ±170% 46.8µs ±152% ~ (p=0.053 n=10+9) name old alloc/op new alloc/op delta TokenTransferLog_Append-8 53.8kB ± 4% 38.6kB ±39% -28.26% (p=0.004 n=8+10) name old allocs/op new allocs/op delta TokenTransferLog_Append-8 384 ± 0% 128 ± 0% -66.67% (p=0.000 n=10+10) --- pkg/core/blockchain.go | 2 +- pkg/core/state/tokens.go | 28 +++++++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index c50e29584..504bebd1e 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1454,7 +1454,7 @@ func appendTokenTransfer(cache *dao.Simple, transCache map[util.Uint160]transfer *nextBatch++ *currTimestamp = bTimestamp // Put makes a copy of it anyway. - log.Raw = log.Raw[:0] + log.Reset() } transCache[addr] = transferData return nil diff --git a/pkg/core/state/tokens.go b/pkg/core/state/tokens.go index c81d4e32d..81739ccdf 100644 --- a/pkg/core/state/tokens.go +++ b/pkg/core/state/tokens.go @@ -16,6 +16,8 @@ const TokenTransferBatchSize = 128 // TokenTransferLog is a serialized log of token transfers. type TokenTransferLog struct { Raw []byte + buf *bytes.Buffer + iow *io.BinWriter } // NEP17Transfer represents a single NEP-17 Transfer event. @@ -111,18 +113,30 @@ func (lg *TokenTransferLog) Append(tr io.Serializable) error { lg.Raw = append(lg.Raw, 0) } - b := bytes.NewBuffer(lg.Raw) - w := io.NewBinWriterFromIO(b) - - tr.EncodeBinary(w) - if w.Err != nil { - return w.Err + if lg.buf == nil { + lg.buf = bytes.NewBuffer(lg.Raw) } - lg.Raw = b.Bytes() + if lg.iow == nil { + lg.iow = io.NewBinWriterFromIO(lg.buf) + } + + tr.EncodeBinary(lg.iow) + if lg.iow.Err != nil { + return lg.iow.Err + } + lg.Raw = lg.buf.Bytes() lg.Raw[0]++ return nil } +// Reset resets the state of the log, clearing all entries, but keeping existing +// buffer for future writes. +func (lg *TokenTransferLog) Reset() { + lg.Raw = lg.Raw[:0] + lg.buf = nil + lg.iow = nil +} + // ForEachNEP11 iterates over a transfer log returning on the first error. func (lg *TokenTransferLog) ForEachNEP11(f func(*NEP11Transfer) (bool, error)) (bool, error) { if lg == nil || len(lg.Raw) == 0 {