From 4d80b4b82c2064b4e6d73214143510079e3517bc Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 2 Apr 2021 19:24:46 +0900 Subject: [PATCH] Improve decoder performance for empty interface type --- decode_interface.go | 117 +++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 46 deletions(-) diff --git a/decode_interface.go b/decode_interface.go index 744b821..d2eafab 100644 --- a/decode_interface.go +++ b/decode_interface.go @@ -8,28 +8,84 @@ import ( ) type interfaceDecoder struct { - typ *rtype - structName string - fieldName string + typ *rtype + structName string + fieldName string + sliceDecoder *sliceDecoder + mapDecoder *mapDecoder + floatDecoder *floatDecoder + numberDecoder *numberDecoder + stringDecoder *stringDecoder +} + +func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder { + ifaceDecoder := &interfaceDecoder{ + typ: emptyInterfaceType, + structName: structName, + fieldName: fieldName, + floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { + *(*interface{})(p) = v + }), + numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) { + *(*interface{})(p) = v + }), + stringDecoder: newStringDecoder(structName, fieldName), + } + ifaceDecoder.sliceDecoder = newSliceDecoder( + ifaceDecoder, + emptyInterfaceType, + emptyInterfaceType.Size(), + structName, fieldName, + ) + ifaceDecoder.mapDecoder = newMapDecoder( + interfaceMapType, + stringType, + ifaceDecoder.stringDecoder, + interfaceMapType.Elem(), + ifaceDecoder, + structName, + fieldName, + ) + return ifaceDecoder } func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder { + emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName) + stringDecoder := newStringDecoder(structName, fieldName) return &interfaceDecoder{ typ: typ, structName: structName, fieldName: fieldName, + sliceDecoder: newSliceDecoder( + emptyIfaceDecoder, + emptyInterfaceType, + emptyInterfaceType.Size(), + structName, fieldName, + ), + mapDecoder: newMapDecoder( + interfaceMapType, + stringType, + stringDecoder, + interfaceMapType.Elem(), + emptyIfaceDecoder, + structName, + fieldName, + ), + floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { + *(*interface{})(p) = v + }), + numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v Number) { + *(*interface{})(p) = v + }), + stringDecoder: stringDecoder, } } func (d *interfaceDecoder) numDecoder(s *stream) decoder { if s.useNumber { - return newNumberDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v Number) { - *(*interface{})(p) = v - }) + return d.numberDecoder } - return newFloatDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v float64) { - *(*interface{})(p) = v - }) + return d.floatDecoder } var ( @@ -122,15 +178,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p case '{': var v map[string]interface{} ptr := unsafe.Pointer(&v) - if err := newMapDecoder( - interfaceMapType, - stringType, - newStringDecoder(d.structName, d.fieldName), - interfaceMapType.Elem(), - newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), - d.structName, - d.fieldName, - ).decodeStream(s, depth, ptr); err != nil { + if err := d.mapDecoder.decodeStream(s, depth, ptr); err != nil { return err } *(*interface{})(p) = v @@ -138,13 +186,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p case '[': var v []interface{} ptr := unsafe.Pointer(&v) - if err := newSliceDecoder( - newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), - emptyInterfaceType, - emptyInterfaceType.Size(), - d.structName, - d.fieldName, - ).decodeStream(s, depth, ptr); err != nil { + if err := d.sliceDecoder.decodeStream(s, depth, ptr); err != nil { return err } *(*interface{})(p) = v @@ -308,15 +350,7 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, case '{': var v map[string]interface{} ptr := unsafe.Pointer(&v) - dec := newMapDecoder( - interfaceMapType, - stringType, - newStringDecoder(d.structName, d.fieldName), - interfaceMapType.Elem(), - newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), - d.structName, d.fieldName, - ) - cursor, err := dec.decode(buf, cursor, depth, ptr) + cursor, err := d.mapDecoder.decode(buf, cursor, depth, ptr) if err != nil { return 0, err } @@ -325,27 +359,18 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64, case '[': var v []interface{} ptr := unsafe.Pointer(&v) - dec := newSliceDecoder( - newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName), - emptyInterfaceType, - emptyInterfaceType.Size(), - d.structName, d.fieldName, - ) - cursor, err := dec.decode(buf, cursor, depth, ptr) + cursor, err := d.sliceDecoder.decode(buf, cursor, depth, ptr) if err != nil { return 0, err } **(**interface{})(unsafe.Pointer(&p)) = v return cursor, nil case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return newFloatDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v float64) { - *(*interface{})(p) = v - }).decode(buf, cursor, depth, p) + return d.floatDecoder.decode(buf, cursor, depth, p) case '"': var v string ptr := unsafe.Pointer(&v) - dec := newStringDecoder(d.structName, d.fieldName) - cursor, err := dec.decode(buf, cursor, depth, ptr) + cursor, err := d.stringDecoder.decode(buf, cursor, depth, ptr) if err != nil { return 0, err }