From af8a4da6d9cbeb372999e8ff4710bb1944bdb561 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 30 Nov 2021 22:30:44 +0300 Subject: [PATCH] stackitem: use type switch more effectively MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the number of allocations, save some time. name old time/op new time/op delta EncodeBinary-8 51.2µs ± 8% 44.6µs ± 7% -12.79% (p=0.008 n=5+5) SerializeSimple-8 523ns ± 5% 449ns ± 4% -14.27% (p=0.008 n=5+5) name old alloc/op new alloc/op delta EncodeBinary-8 329kB ± 0% 329kB ± 0% -0.12% (p=0.008 n=5+5) SerializeSimple-8 432B ± 0% 408B ± 0% -5.56% (p=0.008 n=5+5) name old allocs/op new allocs/op delta EncodeBinary-8 36.0 ± 0% 20.0 ± 0% -44.44% (p=0.008 n=5+5) SerializeSimple-8 7.00 ± 0% 6.00 ± 0% -14.29% (p=0.008 n=5+5) --- pkg/vm/stackitem/serialization.go | 36 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/pkg/vm/stackitem/serialization.go b/pkg/vm/stackitem/serialization.go index 9ee70889b..e11da49c1 100644 --- a/pkg/vm/stackitem/serialization.go +++ b/pkg/vm/stackitem/serialization.go @@ -85,6 +85,18 @@ func EncodeBinaryProtected(item Item, w *io.BinWriter) { w.WriteBytes(sc.data) } +func (w *serContext) writeArray(item Item, arr []Item, start int) error { + w.seen[item] = sliceNoPointer{} + w.appendVarUint(uint64(len(arr))) + for i := range arr { + if err := w.serialize(arr[i]); err != nil { + return err + } + } + w.seen[item] = sliceNoPointer{start, len(w.data)} + return nil +} + func (w *serContext) serialize(item Item) error { if v, ok := w.seen[item]; ok { if v.start == v.end { @@ -127,24 +139,16 @@ func (w *serContext) serialize(item Item) error { } else { return fmt.Errorf("%w: Interop", ErrUnserializable) } - case *Array, *Struct: - w.seen[item] = sliceNoPointer{} - - _, isArray := t.(*Array) - if isArray { - w.data = append(w.data, byte(ArrayT)) - } else { - w.data = append(w.data, byte(StructT)) + case *Array: + w.data = append(w.data, byte(ArrayT)) + if err := w.writeArray(item, t.value, start); err != nil { + return err } - - arr := t.Value().([]Item) - w.appendVarUint(uint64(len(arr))) - for i := range arr { - if err := w.serialize(arr[i]); err != nil { - return err - } + case *Struct: + w.data = append(w.data, byte(StructT)) + if err := w.writeArray(item, t.value, start); err != nil { + return err } - w.seen[item] = sliceNoPointer{start, len(w.data)} case *Map: w.seen[item] = sliceNoPointer{}