stackitem: add some hint to 'seen' maps

It's empirical, we usually have one container, but four is likely to fit most
of regular cases.
This commit is contained in:
Roman Khimov 2021-11-30 19:51:52 +03:00
parent 9576e10d04
commit 3eed9d06f8
3 changed files with 11 additions and 5 deletions

View file

@ -1097,7 +1097,7 @@ func (i *Buffer) Len() int {
// Values of Interop items are not deeply copied. // Values of Interop items are not deeply copied.
// It does preserve duplicates only for non-primitive types. // It does preserve duplicates only for non-primitive types.
func DeepCopy(item Item) Item { func DeepCopy(item Item) Item {
seen := make(map[Item]Item) seen := make(map[Item]Item, typicalNumOfItems)
return deepCopy(item, seen) return deepCopy(item, seen)
} }

View file

@ -42,7 +42,7 @@ var ErrTooDeep = errors.New("too deep")
// Array, Struct -> array // Array, Struct -> array
// Map -> map with keys as UTF-8 bytes // Map -> map with keys as UTF-8 bytes
func ToJSON(item Item) ([]byte, error) { func ToJSON(item Item) ([]byte, error) {
seen := make(map[Item]sliceNoPointer) seen := make(map[Item]sliceNoPointer, typicalNumOfItems)
return toJSON(nil, seen, item) return toJSON(nil, seen, item)
} }
@ -260,7 +260,7 @@ func (d *decoder) decodeMap() (*Map, error) {
// ToJSONWithTypes serializes any stackitem to JSON in a lossless way. // ToJSONWithTypes serializes any stackitem to JSON in a lossless way.
func ToJSONWithTypes(item Item) ([]byte, error) { func ToJSONWithTypes(item Item) ([]byte, error) {
result, err := toJSONWithTypes(item, make(map[Item]bool)) result, err := toJSONWithTypes(item, make(map[Item]bool, typicalNumOfItems))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -13,6 +13,12 @@ import (
// (including itself). // (including itself).
const MaxDeserialized = 2048 const MaxDeserialized = 2048
// typicalNumOfItems is the number of items covering most serializaton needs.
// It's a hint used for map creation, so it's not limiting anything, it's just
// a microoptimization to avoid excessive reallocations. Most of the serialized
// items are structs, so there is at least one of them.
const typicalNumOfItems = 4
// ErrRecursive is returned on attempts to serialize some recursive stack item // ErrRecursive is returned on attempts to serialize some recursive stack item
// (like array including an item with reference to the same array). // (like array including an item with reference to the same array).
var ErrRecursive = errors.New("recursive item") var ErrRecursive = errors.New("recursive item")
@ -40,7 +46,7 @@ type deserContext struct {
func Serialize(item Item) ([]byte, error) { func Serialize(item Item) ([]byte, error) {
sc := serContext{ sc := serContext{
allowInvalid: false, allowInvalid: false,
seen: make(map[Item]sliceNoPointer), seen: make(map[Item]sliceNoPointer, typicalNumOfItems),
} }
err := sc.serialize(item) err := sc.serialize(item)
if err != nil { if err != nil {
@ -69,7 +75,7 @@ func EncodeBinary(item Item, w *io.BinWriter) {
func EncodeBinaryProtected(item Item, w *io.BinWriter) { func EncodeBinaryProtected(item Item, w *io.BinWriter) {
sc := serContext{ sc := serContext{
allowInvalid: true, allowInvalid: true,
seen: make(map[Item]sliceNoPointer), seen: make(map[Item]sliceNoPointer, typicalNumOfItems),
} }
err := sc.serialize(item) err := sc.serialize(item)
if err != nil { if err != nil {