Use sync.Map for caching of decoder

This commit is contained in:
Masaaki Goshima 2020-04-28 18:35:08 +09:00
parent 9034a6fca4
commit 3b27b5f267
1 changed files with 23 additions and 8 deletions

View File

@ -31,13 +31,28 @@ type Decoder struct {
buffered func() io.Reader buffered func() io.Reader
} }
type decoderMap struct {
sync.Map
}
func (m *decoderMap) Get(k string) decoder {
if v, ok := m.Load(k); ok {
return v.(decoder)
}
return nil
}
func (m *decoderMap) Set(k string, dec decoder) {
m.Store(k, dec)
}
var ( var (
ctxPool sync.Pool ctxPool sync.Pool
cachedDecoder map[string]decoder cachedDecoder decoderMap
) )
func init() { func init() {
cachedDecoder = map[string]decoder{} cachedDecoder = decoderMap{}
ctxPool = sync.Pool{ ctxPool = sync.Pool{
New: func() interface{} { New: func() interface{} {
return newContext() return newContext()
@ -65,14 +80,14 @@ func (d *Decoder) decode(src []byte, header *interfaceHeader) error {
return ErrDecodePointer return ErrDecodePointer
} }
name := typ.String() name := typ.String()
dec, exists := cachedDecoder[name] dec := cachedDecoder.Get(name)
if !exists { if dec == nil {
compiledDec, err := d.compile(typ.Elem()) compiledDec, err := d.compile(typ.Elem())
if err != nil { if err != nil {
return err return err
} }
if name != "" { if name != "" {
cachedDecoder[name] = compiledDec cachedDecoder.Set(name, compiledDec)
} }
dec = compiledDec dec = compiledDec
} }
@ -110,14 +125,14 @@ func (d *Decoder) Decode(v interface{}) error {
return ErrDecodePointer return ErrDecodePointer
} }
name := typ.String() name := typ.String()
dec, exists := cachedDecoder[name] dec := cachedDecoder.Get(name)
if !exists { if dec == nil {
compiledDec, err := d.compile(typ.Elem()) compiledDec, err := d.compile(typ.Elem())
if err != nil { if err != nil {
return err return err
} }
if name != "" { if name != "" {
cachedDecoder[name] = compiledDec cachedDecoder.Set(name, compiledDec)
} }
dec = compiledDec dec = compiledDec
} }