mirror of
https://github.com/gohugoio/hugo.git
synced 2025-04-26 05:30:54 +03:00
common/hreflect: Replace the map/RWMutex method cache with sync.Map
It's much faster when running in parallel: ``` GetMethodByName-10 125.1n ± 6% 181.7n ± 7% +45.30% (p=0.002 n=6) GetMethodByNamePara-10 770.10n ± 1% 24.77n ± 9% -96.78% (p=0.002 n=6) ```
This commit is contained in:
parent
26d986fc0d
commit
8d2379bcb3
2 changed files with 19 additions and 16 deletions
|
@ -134,12 +134,7 @@ type methodKey struct {
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
type methods struct {
|
var methodCache sync.Map
|
||||||
sync.RWMutex
|
|
||||||
cache map[methodKey]int
|
|
||||||
}
|
|
||||||
|
|
||||||
var methodCache = &methods{cache: make(map[methodKey]int)}
|
|
||||||
|
|
||||||
// GetMethodByName is the same as reflect.Value.MethodByName, but it caches the
|
// GetMethodByName is the same as reflect.Value.MethodByName, but it caches the
|
||||||
// type lookup.
|
// type lookup.
|
||||||
|
@ -157,22 +152,16 @@ func GetMethodByName(v reflect.Value, name string) reflect.Value {
|
||||||
// -1 if no such method exists.
|
// -1 if no such method exists.
|
||||||
func GetMethodIndexByName(tp reflect.Type, name string) int {
|
func GetMethodIndexByName(tp reflect.Type, name string) int {
|
||||||
k := methodKey{tp, name}
|
k := methodKey{tp, name}
|
||||||
methodCache.RLock()
|
v, found := methodCache.Load(k)
|
||||||
index, found := methodCache.cache[k]
|
|
||||||
methodCache.RUnlock()
|
|
||||||
if found {
|
if found {
|
||||||
return index
|
return v.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
methodCache.Lock()
|
|
||||||
defer methodCache.Unlock()
|
|
||||||
|
|
||||||
m, ok := tp.MethodByName(name)
|
m, ok := tp.MethodByName(name)
|
||||||
index = m.Index
|
index := m.Index
|
||||||
if !ok {
|
if !ok {
|
||||||
index = -1
|
index = -1
|
||||||
}
|
}
|
||||||
methodCache.cache[k] = index
|
methodCache.Store(k, index)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return -1
|
return -1
|
||||||
|
|
|
@ -134,3 +134,17 @@ func BenchmarkGetMethodByName(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkGetMethodByNamePara(b *testing.B) {
|
||||||
|
v := reflect.ValueOf(&testStruct{})
|
||||||
|
methods := []string{"Method1", "Method2", "Method3", "Method4", "Method5"}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
for pb.Next() {
|
||||||
|
for _, method := range methods {
|
||||||
|
_ = GetMethodByName(v, method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue