summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-07-27 19:20:48 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-07-27 19:23:12 +0200
commit4d7af757c99a561744c87c477d10b89e5c9d7e35 (patch)
treed37b0d3fb9d5e6836737364a75c3dc53acff5559 /common
parent7f058b8bab947db98939ed27a7c2a08468323d08 (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.go44
-rw-r--r--common/hstrings/strings_test.go22
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+`)
+ }
+}