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