diff --git a/proto/table_marshal.go b/proto/table_marshal.go index f8babdefab..152d0aae54 100644 --- a/proto/table_marshal.go +++ b/proto/table_marshal.go @@ -96,7 +96,7 @@ type marshalElemInfo struct { var ( marshalInfoMap = map[reflect.Type]*marshalInfo{} - marshalInfoLock sync.Mutex + marshalInfoLock sync.RWMutex uint8SliceType = reflect.TypeOf(([]uint8)(nil)).Kind() ) @@ -105,8 +105,14 @@ var ( // The info it returns may not necessarily initialized. // t is the type of the message (NOT the pointer to it). func getMarshalInfo(t reflect.Type) *marshalInfo { - marshalInfoLock.Lock() + marshalInfoLock.RLock() u, ok := marshalInfoMap[t] + marshalInfoLock.RUnlock() + if ok { + return u + } + marshalInfoLock.Lock() + u, ok = marshalInfoMap[t] if !ok { u = &marshalInfo{typ: t} marshalInfoMap[t] = u diff --git a/proto/table_unmarshal.go b/proto/table_unmarshal.go index 937229386a..5a535e1a90 100644 --- a/proto/table_unmarshal.go +++ b/proto/table_unmarshal.go @@ -105,7 +105,7 @@ type unmarshalFieldInfo struct { var ( unmarshalInfoMap = map[reflect.Type]*unmarshalInfo{} - unmarshalInfoLock sync.Mutex + unmarshalInfoLock sync.RWMutex ) // getUnmarshalInfo returns the data structure which can be @@ -116,10 +116,17 @@ func getUnmarshalInfo(t reflect.Type) *unmarshalInfo { // unconditionally. We would end up allocating one // per occurrence of that type as a message or submessage. // We use a cache here just to reduce memory usage. + unmarshalInfoLock.RLock() + u, ok := unmarshalInfoMap[t] + unmarshalInfoLock.RUnlock() + if ok { + return u + } + unmarshalInfoLock.Lock() defer unmarshalInfoLock.Unlock() - u := unmarshalInfoMap[t] - if u == nil { + u, ok = unmarshalInfoMap[t] + if !ok { u = &unmarshalInfo{typ: t} // Note: we just set the type here. The rest of the fields // will be initialized on first use.