diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2025-03-26 11:11:06 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2025-03-26 14:24:51 +0100 |
commit | 8d2379bcb3ca4c5fdf6b9322bbe05e42b7a81bca (patch) | |
tree | 00bef0ce6f1314613de72ebbfe3f8946d39271e6 | |
parent | 26d986fc0d872ee0b01d776229486e22929b36b0 (diff) | |
download | hugo-8d2379bcb3ca4c5fdf6b9322bbe05e42b7a81bca.tar.gz hugo-8d2379bcb3ca4c5fdf6b9322bbe05e42b7a81bca.zip |
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)
```
-rw-r--r-- | common/hreflect/helpers.go | 21 | ||||
-rw-r--r-- | common/hreflect/helpers_test.go | 14 |
2 files changed, 19 insertions, 16 deletions
diff --git a/common/hreflect/helpers.go b/common/hreflect/helpers.go index ab7883a47..545371374 100644 --- a/common/hreflect/helpers.go +++ b/common/hreflect/helpers.go @@ -134,12 +134,7 @@ type methodKey struct { 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. @@ -157,22 +152,16 @@ func GetMethodByName(v reflect.Value, name string) reflect.Value { // -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 diff --git a/common/hreflect/helpers_test.go b/common/hreflect/helpers_test.go index 119722261..cbcad0f22 100644 --- a/common/hreflect/helpers_test.go +++ b/common/hreflect/helpers_test.go @@ -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) + } + } + }) +} |