name string
}
-type methods struct {
- sync.RWMutex
- cache map[methodKey]int
-}
-
-var methodCache = &methods{cache: make(map[methodKey]int)}
+var methodCache sync.Map
// GetMethodByName is the same as reflect.Value.MethodByName, but it caches the
// type lookup.
// -1 if no such method exists.
func GetMethodIndexByName(tp reflect.Type, name string) int {
k := methodKey{tp, name}
- methodCache.RLock()
- index, found := methodCache.cache[k]
- methodCache.RUnlock()
+ v, found := methodCache.Load(k)
if found {
- return index
+ return v.(int)
}
-
- methodCache.Lock()
- defer methodCache.Unlock()
-
m, ok := tp.MethodByName(name)
- index = m.Index
+ index := m.Index
if !ok {
index = -1
}
- methodCache.cache[k] = index
+ methodCache.Store(k, index)
if !ok {
return -1
}
}
}
+
+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)
+ }
+ }
+ })
+}