diff --git a/model/labels/matcher_test.go b/model/labels/matcher_test.go index 14615a50d..d26e9329f 100644 --- a/model/labels/matcher_test.go +++ b/model/labels/matcher_test.go @@ -102,12 +102,12 @@ func TestInverse(t *testing.T) { expected: &Matcher{Type: MatchEqual, Name: "name2", Value: "value2"}, }, { - matcher: &Matcher{Type: MatchRegexp, Name: "name3", Value: "value3"}, - expected: &Matcher{Type: MatchNotRegexp, Name: "name3", Value: "value3"}, + matcher: &Matcher{Type: MatchRegexp, Name: "name3", Value: "value3.*"}, + expected: &Matcher{Type: MatchNotRegexp, Name: "name3", Value: "value3.*"}, }, { - matcher: &Matcher{Type: MatchNotRegexp, Name: "name4", Value: "value4"}, - expected: &Matcher{Type: MatchRegexp, Name: "name4", Value: "value4"}, + matcher: &Matcher{Type: MatchNotRegexp, Name: "name4", Value: "value4.*"}, + expected: &Matcher{Type: MatchRegexp, Name: "name4", Value: "value4.*"}, }, } @@ -123,3 +123,13 @@ func BenchmarkMatchType_String(b *testing.B) { _ = MatchType(i % int(MatchNotRegexp+1)).String() } } + +func BenchmarkNewMatcher(b *testing.B) { + b.Run("regex matcher with literal", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i <= b.N; i++ { + NewMatcher(MatchRegexp, "foo", "bar") + } + }) +} diff --git a/model/labels/regexp.go b/model/labels/regexp.go index e09a63772..14319c7f7 100644 --- a/model/labels/regexp.go +++ b/model/labels/regexp.go @@ -25,9 +25,16 @@ type FastRegexMatcher struct { prefix string suffix string contains string + + // shortcut for literals + literal bool + value string } func NewFastRegexMatcher(v string) (*FastRegexMatcher, error) { + if isLiteral(v) { + return &FastRegexMatcher{literal: true, value: v}, nil + } re, err := regexp.Compile("^(?:" + v + ")$") if err != nil { return nil, err @@ -50,6 +57,9 @@ func NewFastRegexMatcher(v string) (*FastRegexMatcher, error) { } func (m *FastRegexMatcher) MatchString(s string) bool { + if m.literal { + return s == m.value + } if m.prefix != "" && !strings.HasPrefix(s, m.prefix) { return false } @@ -63,9 +73,16 @@ func (m *FastRegexMatcher) MatchString(s string) bool { } func (m *FastRegexMatcher) GetRegexString() string { + if m.literal { + return m.value + } return m.re.String() } +func isLiteral(re string) bool { + return regexp.QuoteMeta(re) == re +} + // optimizeConcatRegex returns literal prefix/suffix text that can be safely // checked against the label value before running the regexp matcher. func optimizeConcatRegex(r *syntax.Regexp) (prefix, suffix, contains string) {