Improve decoder performance for empty interface type

This commit is contained in:
Masaaki Goshima 2021-04-02 19:24:46 +09:00
parent 2dda80b368
commit 4d80b4b82c
1 changed files with 71 additions and 46 deletions

View File

@ -8,28 +8,84 @@ import (
) )
type interfaceDecoder struct { type interfaceDecoder struct {
typ *rtype typ *rtype
structName string structName string
fieldName 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 { func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder {
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
stringDecoder := newStringDecoder(structName, fieldName)
return &interfaceDecoder{ return &interfaceDecoder{
typ: typ, typ: typ,
structName: structName, structName: structName,
fieldName: fieldName, 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 { func (d *interfaceDecoder) numDecoder(s *stream) decoder {
if s.useNumber { if s.useNumber {
return newNumberDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v Number) { return d.numberDecoder
*(*interface{})(p) = v
})
} }
return newFloatDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v float64) { return d.floatDecoder
*(*interface{})(p) = v
})
} }
var ( var (
@ -122,15 +178,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
case '{': case '{':
var v map[string]interface{} var v map[string]interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
if err := newMapDecoder( if err := d.mapDecoder.decodeStream(s, depth, ptr); err != nil {
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 {
return err return err
} }
*(*interface{})(p) = v *(*interface{})(p) = v
@ -138,13 +186,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p
case '[': case '[':
var v []interface{} var v []interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
if err := newSliceDecoder( if err := d.sliceDecoder.decodeStream(s, depth, ptr); err != nil {
newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName),
emptyInterfaceType,
emptyInterfaceType.Size(),
d.structName,
d.fieldName,
).decodeStream(s, depth, ptr); err != nil {
return err return err
} }
*(*interface{})(p) = v *(*interface{})(p) = v
@ -308,15 +350,7 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
case '{': case '{':
var v map[string]interface{} var v map[string]interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
dec := newMapDecoder( cursor, err := d.mapDecoder.decode(buf, cursor, depth, ptr)
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)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -325,27 +359,18 @@ func (d *interfaceDecoder) decodeEmptyInterface(buf []byte, cursor, depth int64,
case '[': case '[':
var v []interface{} var v []interface{}
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
dec := newSliceDecoder( cursor, err := d.sliceDecoder.decode(buf, cursor, depth, ptr)
newInterfaceDecoder(emptyInterfaceType, d.structName, d.fieldName),
emptyInterfaceType,
emptyInterfaceType.Size(),
d.structName, d.fieldName,
)
cursor, err := dec.decode(buf, cursor, depth, ptr)
if err != nil { if err != nil {
return 0, err return 0, err
} }
**(**interface{})(unsafe.Pointer(&p)) = v **(**interface{})(unsafe.Pointer(&p)) = v
return cursor, nil return cursor, nil
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return newFloatDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v float64) { return d.floatDecoder.decode(buf, cursor, depth, p)
*(*interface{})(p) = v
}).decode(buf, cursor, depth, p)
case '"': case '"':
var v string var v string
ptr := unsafe.Pointer(&v) ptr := unsafe.Pointer(&v)
dec := newStringDecoder(d.structName, d.fieldName) cursor, err := d.stringDecoder.decode(buf, cursor, depth, ptr)
cursor, err := dec.decode(buf, cursor, depth, ptr)
if err != nil { if err != nil {
return 0, err return 0, err
} }