lib/promrelabel: call PromRegex.MatchString() on a slow path only if it contains non-empty literal prefix

This should improve slow path speed for regexps without literal prefixes
This commit is contained in:
Aliaksandr Valialkin 2022-08-26 21:47:20 +03:00
parent 30fb4b948e
commit a2cd79576f
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
2 changed files with 19 additions and 12 deletions

View file

@ -203,7 +203,7 @@ func (prc *parsedRelabelConfig) apply(labels []prompbmarshal.Label, labelsOffset
return labels
}
}
if !prc.regex.MatchString(bytesutil.ToUnsafeString(bb.B)) {
if re := prc.regex; re.HasPrefix() && !re.MatchString(bytesutil.ToUnsafeString(bb.B)) {
// Fast path - regexp mismatch.
relabelBufPool.Put(bb)
return labels
@ -304,8 +304,7 @@ func (prc *parsedRelabelConfig) apply(labels []prompbmarshal.Label, labelsOffset
return setLabelValue(labels, labelsOffset, prc.TargetLabel, value)
case "labelmap":
// Replace label names with the `replacement` if they match `regex`
for i := range src {
label := &src[i]
for _, label := range src {
labelName, ok := prc.replaceFullString(label.Name, prc.Replacement, prc.hasCaptureGroupInReplacement)
if ok {
labels = setLabelValue(labels, labelsOffset, labelName, label.Value)
@ -322,20 +321,20 @@ func (prc *parsedRelabelConfig) apply(labels []prompbmarshal.Label, labelsOffset
case "labeldrop":
// Drop labels with names matching the `regex`
dst := labels[:labelsOffset]
for i := range src {
label := &src[i]
if !prc.regex.MatchString(label.Name) {
dst = append(dst, *label)
re := prc.regex
for _, label := range src {
if !re.MatchString(label.Name) {
dst = append(dst, label)
}
}
return dst
case "labelkeep":
// Keep labels with names matching the `regex`
dst := labels[:labelsOffset]
for i := range src {
label := &src[i]
if prc.regex.MatchString(label.Name) {
dst = append(dst, *label)
re := prc.regex
for _, label := range src {
if re.MatchString(label.Name) {
dst = append(dst, label)
}
}
return dst
@ -393,7 +392,7 @@ func (prc *parsedRelabelConfig) replaceFullString(s, replacement string, hasCapt
}
}
}
if !prc.regex.MatchString(s) {
if re := prc.regex; re.HasPrefix() && !re.MatchString(s) {
// Fast path - regex mismatch
return s, false
}

View file

@ -61,6 +61,14 @@ func NewPromRegex(expr string) (*PromRegex, error) {
return pr, nil
}
// HasPrefix returns true if pr contains non-empty literal prefix.
//
// For example, if pr is "foo(bar|baz)", then the prefix is "foo",
// so HasPrefix() returns true.
func (pr *PromRegex) HasPrefix() bool {
return len(pr.prefix) > 0
}
// MatchString retruns true if s matches pr.
//
// The pr is automatically anchored to the beginning and to the end