diff --git a/util/builtin_operators.go b/util/builtin_operators.go index 37d9cb5bf..7f52a6ea1 100644 --- a/util/builtin_operators.go +++ b/util/builtin_operators.go @@ -332,11 +332,8 @@ func KeyMatch5Func(args ...interface{}) (interface{}, error) { // RegexMatch determines whether key1 matches the pattern of key2 in regular expression. func RegexMatch(key1 string, key2 string) bool { - res, err := regexp.MatchString(key2, key1) - if err != nil { - panic(err) - } - return res + re := mustCompileOrGet(key2) + return re.MatchString(key1) } // RegexMatchFunc is the wrapper for RegexMatch. diff --git a/util/builtin_operators_test.go b/util/builtin_operators_test.go index ba0f463db..c98549d77 100644 --- a/util/builtin_operators_test.go +++ b/util/builtin_operators_test.go @@ -662,3 +662,40 @@ func TestTestMatch(t *testing.T) { testTimeMatch(t, "0000-01-01 00:00:00", "_", true) testTimeMatch(t, "9999-12-30 00:00:00", "_", false) } + +// BenchmarkRegexMatch benchmarks the RegexMatch function with cached regex compilation +func BenchmarkRegexMatch(b *testing.B) { +patterns := []string{ +"/topic/create", +"/topic/edit/[0-9]+", +"/topic/delete/[0-9]+", +"^/api/[a-z]+/[0-9]+$", +"^/resource/[a-zA-Z0-9_-]+/action$", +} +inputs := []string{ +"/topic/create", +"/topic/edit/123", +"/topic/delete/456", +"/api/users/789", +"/resource/test_resource/action", +} + +b.ResetTimer() +for i := 0; i < b.N; i++ { +pattern := patterns[i%len(patterns)] +input := inputs[i%len(inputs)] +RegexMatch(input, pattern) +} +} + +// BenchmarkRegexMatchSamePattern benchmarks RegexMatch with the same pattern repeatedly +// This demonstrates the caching benefit +func BenchmarkRegexMatchSamePattern(b *testing.B) { +pattern := "/topic/edit/[0-9]+" +input := "/topic/edit/123" + +b.ResetTimer() +for i := 0; i < b.N; i++ { +RegexMatch(input, pattern) +} +}