diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2023-07-27 19:20:48 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2023-07-27 19:23:12 +0200 |
commit | 4d7af757c99a561744c87c477d10b89e5c9d7e35 (patch) | |
tree | d37b0d3fb9d5e6836737364a75c3dc53acff5559 /common | |
parent | 7f058b8bab947db98939ed27a7c2a08468323d08 (diff) |
Add a common regexp cache
```
BenchmarkGetOrCompileRegexp-10 73959368 13.71 ns/op 0 B/op 0 allocs/op
BenchmarkCompileRegexp-10 3143529 380.1 ns/op 872 B/op 10 allocs/op
```
Diffstat (limited to 'common')
-rw-r--r-- | common/hstrings/strings.go | 44 | ||||
-rw-r--r-- | common/hstrings/strings_test.go | 22 |
2 files changed, 66 insertions, 0 deletions
diff --git a/common/hstrings/strings.go b/common/hstrings/strings.go index 6c0f820fe..2fd791f43 100644 --- a/common/hstrings/strings.go +++ b/common/hstrings/strings.go @@ -15,7 +15,9 @@ package hstrings import ( "fmt" + "regexp" "strings" + "sync" "github.com/gohugoio/hugo/compare" ) @@ -55,3 +57,45 @@ func EqualAny(a string, b ...string) bool { } return false } + +// regexpCache represents a cache of regexp objects protected by a mutex. +type regexpCache struct { + mu sync.RWMutex + re map[string]*regexp.Regexp +} + +func (rc *regexpCache) getOrCompileRegexp(pattern string) (re *regexp.Regexp, err error) { + var ok bool + + if re, ok = rc.get(pattern); !ok { + re, err = regexp.Compile(pattern) + if err != nil { + return nil, err + } + rc.set(pattern, re) + } + + return re, nil +} + +func (rc *regexpCache) get(key string) (re *regexp.Regexp, ok bool) { + rc.mu.RLock() + re, ok = rc.re[key] + rc.mu.RUnlock() + return +} + +func (rc *regexpCache) set(key string, re *regexp.Regexp) { + rc.mu.Lock() + rc.re[key] = re + rc.mu.Unlock() +} + +var reCache = regexpCache{re: make(map[string]*regexp.Regexp)} + +// GetOrCompileRegexp retrieves a regexp object from the cache based upon the pattern. +// If the pattern is not found in the cache, the pattern is compiled and added to +// the cache. +func GetOrCompileRegexp(pattern string) (re *regexp.Regexp, err error) { + return reCache.getOrCompileRegexp(pattern) +} diff --git a/common/hstrings/strings_test.go b/common/hstrings/strings_test.go index dc2eae6f2..85068bdf9 100644 --- a/common/hstrings/strings_test.go +++ b/common/hstrings/strings_test.go @@ -14,6 +14,7 @@ package hstrings import ( + "regexp" "testing" qt "github.com/frankban/quicktest" @@ -34,3 +35,24 @@ func TestStringEqualFold(t *testing.T) { c.Assert(StringEqualFold(s1).Eq("b"), qt.Equals, false) } + +func TestGetOrCompileRegexp(t *testing.T) { + c := qt.New(t) + + re, err := GetOrCompileRegexp(`\d+`) + c.Assert(err, qt.IsNil) + c.Assert(re.MatchString("123"), qt.Equals, true) + +} + +func BenchmarkGetOrCompileRegexp(b *testing.B) { + for i := 0; i < b.N; i++ { + GetOrCompileRegexp(`\d+`) + } +} + +func BenchmarkCompileRegexp(b *testing.B) { + for i := 0; i < b.N; i++ { + regexp.MustCompile(`\d+`) + } +} |