summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2025-03-26 11:11:06 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2025-03-26 14:24:51 +0100
commit8d2379bcb3ca4c5fdf6b9322bbe05e42b7a81bca (patch)
tree00bef0ce6f1314613de72ebbfe3f8946d39271e6
parent26d986fc0d872ee0b01d776229486e22929b36b0 (diff)
downloadhugo-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.go21
-rw-r--r--common/hreflect/helpers_test.go14
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)
+ }
+ }
+ })
+}