Minimal shared cache for struct field paths
This commit is contained in:
+32
-1
@@ -5,6 +5,7 @@ import (
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type target interface {
|
||||
@@ -466,10 +467,37 @@ func scopeMap(v reflect.Value, name string) (target, bool, error) {
|
||||
}, true, nil
|
||||
}
|
||||
|
||||
type fieldPathsMap = map[string][]int
|
||||
|
||||
type fieldPathsCache struct {
|
||||
m map[reflect.Type]fieldPathsMap
|
||||
l sync.RWMutex
|
||||
}
|
||||
|
||||
func (c *fieldPathsCache) get(t reflect.Type) (fieldPathsMap, bool) {
|
||||
c.l.RLock()
|
||||
paths, ok := c.m[t]
|
||||
c.l.RUnlock()
|
||||
return paths, ok
|
||||
}
|
||||
|
||||
func (c *fieldPathsCache) set(t reflect.Type, m fieldPathsMap) {
|
||||
c.l.Lock()
|
||||
c.m[t] = m
|
||||
c.l.Unlock()
|
||||
}
|
||||
|
||||
var globalFieldPathsCache = fieldPathsCache{
|
||||
m: map[reflect.Type]fieldPathsMap{},
|
||||
l: sync.RWMutex{},
|
||||
}
|
||||
|
||||
func scopeStruct(v reflect.Value, name string) (target, bool, error) {
|
||||
// TODO: cache this, and reduce allocations
|
||||
|
||||
fieldPaths := map[string][]int{}
|
||||
fieldPaths, ok := globalFieldPathsCache.get(v.Type())
|
||||
if !ok {
|
||||
fieldPaths = map[string][]int{}
|
||||
|
||||
path := make([]int, 0, 16)
|
||||
var walk func(reflect.Value)
|
||||
@@ -502,6 +530,9 @@ func scopeStruct(v reflect.Value, name string) (target, bool, error) {
|
||||
|
||||
walk(v)
|
||||
|
||||
globalFieldPathsCache.set(v.Type(), fieldPaths)
|
||||
}
|
||||
|
||||
path, ok := fieldPaths[name]
|
||||
if !ok {
|
||||
path, ok = fieldPaths[strings.ToLower(name)]
|
||||
|
||||
Reference in New Issue
Block a user