From 197ecca42630fffcff7a453c0ae666407e23a1c6 Mon Sep 17 00:00:00 2001
From: Aliaksandr Valialkin <valyala@gmail.com>
Date: Mon, 22 Feb 2021 16:33:55 +0200
Subject: [PATCH] lib/promrelabel: add more optimizations for relabeling for
 common cases

---
 app/vmagent/remotewrite/relabel.go     |  12 +-
 app/vmagent/remotewrite/remotewrite.go |  12 +-
 app/vminsert/relabel/relabel.go        |  26 +-
 lib/promrelabel/config.go              | 100 ++--
 lib/promrelabel/config_test.go         |  43 +-
 lib/promrelabel/relabel.go             | 185 +++----
 lib/promrelabel/relabel_test.go        | 646 ++++++++++++-------------
 lib/promrelabel/relabel_timing_test.go | 350 +++++++-------
 lib/promscrape/config.go               |  12 +-
 lib/promscrape/config_test.go          |  20 +-
 lib/promscrape/scrapework.go           |  15 +-
 lib/promscrape/scrapework_test.go      |  55 ++-
 12 files changed, 751 insertions(+), 725 deletions(-)

diff --git a/app/vmagent/remotewrite/relabel.go b/app/vmagent/remotewrite/relabel.go
index 8756941734..ad7c967f6c 100644
--- a/app/vmagent/remotewrite/relabel.go
+++ b/app/vmagent/remotewrite/relabel.go
@@ -41,7 +41,7 @@ func loadRelabelConfigs() (*relabelConfigs, error) {
 		return nil, fmt.Errorf("too many -remoteWrite.urlRelabelConfig args: %d; it mustn't exceed the number of -remoteWrite.url args: %d",
 			len(*relabelConfigPaths), len(*remoteWriteURLs))
 	}
-	rcs.perURL = make([][]promrelabel.ParsedRelabelConfig, len(*remoteWriteURLs))
+	rcs.perURL = make([]*promrelabel.ParsedConfigs, len(*remoteWriteURLs))
 	for i, path := range *relabelConfigPaths {
 		if len(path) == 0 {
 			// Skip empty relabel config.
@@ -57,8 +57,8 @@ func loadRelabelConfigs() (*relabelConfigs, error) {
 }
 
 type relabelConfigs struct {
-	global []promrelabel.ParsedRelabelConfig
-	perURL [][]promrelabel.ParsedRelabelConfig
+	global *promrelabel.ParsedConfigs
+	perURL []*promrelabel.ParsedConfigs
 }
 
 // initLabelsGlobal must be called after parsing command-line flags.
@@ -79,8 +79,8 @@ func initLabelsGlobal() {
 	}
 }
 
-func (rctx *relabelCtx) applyRelabeling(tss []prompbmarshal.TimeSeries, extraLabels []prompbmarshal.Label, prcs []promrelabel.ParsedRelabelConfig) []prompbmarshal.TimeSeries {
-	if len(extraLabels) == 0 && len(prcs) == 0 {
+func (rctx *relabelCtx) applyRelabeling(tss []prompbmarshal.TimeSeries, extraLabels []prompbmarshal.Label, pcs *promrelabel.ParsedConfigs) []prompbmarshal.TimeSeries {
+	if len(extraLabels) == 0 && pcs.Len() == 0 {
 		// Nothing to change.
 		return tss
 	}
@@ -100,7 +100,7 @@ func (rctx *relabelCtx) applyRelabeling(tss []prompbmarshal.TimeSeries, extraLab
 				labels = append(labels, *extraLabel)
 			}
 		}
-		labels = promrelabel.ApplyRelabelConfigs(labels, labelsLen, prcs, true)
+		labels = pcs.Apply(labels, labelsLen, true)
 		if len(labels) == labelsLen {
 			// Drop the current time series, since relabeling removed all the labels.
 			continue
diff --git a/app/vmagent/remotewrite/remotewrite.go b/app/vmagent/remotewrite/remotewrite.go
index 824ea9ad77..4e5ef67517 100644
--- a/app/vmagent/remotewrite/remotewrite.go
+++ b/app/vmagent/remotewrite/remotewrite.go
@@ -142,8 +142,8 @@ func Stop() {
 func Push(wr *prompbmarshal.WriteRequest) {
 	var rctx *relabelCtx
 	rcs := allRelabelConfigs.Load().(*relabelConfigs)
-	prcsGlobal := rcs.global
-	if len(prcsGlobal) > 0 || len(labelsGlobal) > 0 {
+	pcsGlobal := rcs.global
+	if pcsGlobal.Len() > 0 || len(labelsGlobal) > 0 {
 		rctx = getRelabelCtx()
 	}
 	tss := wr.Timeseries
@@ -167,7 +167,7 @@ func Push(wr *prompbmarshal.WriteRequest) {
 		}
 		if rctx != nil {
 			tssBlockLen := len(tssBlock)
-			tssBlock = rctx.applyRelabeling(tssBlock, labelsGlobal, prcsGlobal)
+			tssBlock = rctx.applyRelabeling(tssBlock, labelsGlobal, pcsGlobal)
 			globalRelabelMetricsDropped.Add(tssBlockLen - len(tssBlock))
 		}
 		for _, rwctx := range rwctxs {
@@ -240,8 +240,8 @@ func (rwctx *remoteWriteCtx) Push(tss []prompbmarshal.TimeSeries) {
 	var rctx *relabelCtx
 	var v *[]prompbmarshal.TimeSeries
 	rcs := allRelabelConfigs.Load().(*relabelConfigs)
-	prcs := rcs.perURL[rwctx.idx]
-	if len(prcs) > 0 {
+	pcs := rcs.perURL[rwctx.idx]
+	if pcs.Len() > 0 {
 		rctx = getRelabelCtx()
 		// Make a copy of tss before applying relabeling in order to prevent
 		// from affecting time series for other remoteWrite.url configs.
@@ -250,7 +250,7 @@ func (rwctx *remoteWriteCtx) Push(tss []prompbmarshal.TimeSeries) {
 		v = tssRelabelPool.Get().(*[]prompbmarshal.TimeSeries)
 		tss = append(*v, tss...)
 		tssLen := len(tss)
-		tss = rctx.applyRelabeling(tss, nil, prcs)
+		tss = rctx.applyRelabeling(tss, nil, pcs)
 		rwctx.relabelMetricsDropped.Add(tssLen - len(tss))
 	}
 	pss := rwctx.pss
diff --git a/app/vminsert/relabel/relabel.go b/app/vminsert/relabel/relabel.go
index 11b9cc774f..b9a2e62e44 100644
--- a/app/vminsert/relabel/relabel.go
+++ b/app/vminsert/relabel/relabel.go
@@ -19,11 +19,11 @@ var relabelConfig = flag.String("relabelConfig", "", "Optional path to a file wi
 
 // Init must be called after flag.Parse and before using the relabel package.
 func Init() {
-	prcs, err := loadRelabelConfig()
+	pcs, err := loadRelabelConfig()
 	if err != nil {
 		logger.Fatalf("cannot load relabelConfig: %s", err)
 	}
-	prcsGlobal.Store(&prcs)
+	pcsGlobal.Store(pcs)
 	if len(*relabelConfig) == 0 {
 		return
 	}
@@ -31,34 +31,34 @@ func Init() {
 	go func() {
 		for range sighupCh {
 			logger.Infof("received SIGHUP; reloading -relabelConfig=%q...", *relabelConfig)
-			prcs, err := loadRelabelConfig()
+			pcs, err := loadRelabelConfig()
 			if err != nil {
 				logger.Errorf("cannot load the updated relabelConfig: %s; preserving the previous config", err)
 				continue
 			}
-			prcsGlobal.Store(&prcs)
+			pcsGlobal.Store(pcs)
 			logger.Infof("successfully reloaded -relabelConfig=%q", *relabelConfig)
 		}
 	}()
 }
 
-var prcsGlobal atomic.Value
+var pcsGlobal atomic.Value
 
-func loadRelabelConfig() ([]promrelabel.ParsedRelabelConfig, error) {
+func loadRelabelConfig() (*promrelabel.ParsedConfigs, error) {
 	if len(*relabelConfig) == 0 {
 		return nil, nil
 	}
-	prcs, err := promrelabel.LoadRelabelConfigs(*relabelConfig)
+	pcs, err := promrelabel.LoadRelabelConfigs(*relabelConfig)
 	if err != nil {
 		return nil, fmt.Errorf("error when reading -relabelConfig=%q: %w", *relabelConfig, err)
 	}
-	return prcs, nil
+	return pcs, nil
 }
 
 // HasRelabeling returns true if there is global relabeling.
 func HasRelabeling() bool {
-	prcs := prcsGlobal.Load().(*[]promrelabel.ParsedRelabelConfig)
-	return len(*prcs) > 0
+	pcs := pcsGlobal.Load().(*promrelabel.ParsedConfigs)
+	return pcs.Len() > 0
 }
 
 // Ctx holds relabeling context.
@@ -77,8 +77,8 @@ func (ctx *Ctx) Reset() {
 //
 // The returned labels are valid until the next call to ApplyRelabeling.
 func (ctx *Ctx) ApplyRelabeling(labels []prompb.Label) []prompb.Label {
-	prcs := prcsGlobal.Load().(*[]promrelabel.ParsedRelabelConfig)
-	if len(*prcs) == 0 {
+	pcs := pcsGlobal.Load().(*promrelabel.ParsedConfigs)
+	if pcs.Len() == 0 {
 		// There are no relabeling rules.
 		return labels
 	}
@@ -97,7 +97,7 @@ func (ctx *Ctx) ApplyRelabeling(labels []prompb.Label) []prompb.Label {
 	}
 
 	// Apply relabeling
-	tmpLabels = promrelabel.ApplyRelabelConfigs(tmpLabels, 0, *prcs, true)
+	tmpLabels = pcs.Apply(tmpLabels, 0, true)
 	ctx.tmpLabels = tmpLabels
 	if len(tmpLabels) == 0 {
 		metricsDropped.Inc()
diff --git a/lib/promrelabel/config.go b/lib/promrelabel/config.go
index abd9419a4d..29d624174a 100644
--- a/lib/promrelabel/config.go
+++ b/lib/promrelabel/config.go
@@ -23,38 +23,78 @@ type RelabelConfig struct {
 	Action       string   `yaml:"action,omitempty"`
 }
 
+// ParsedConfigs represents parsed relabel configs.
+type ParsedConfigs struct {
+	prcs []*parsedRelabelConfig
+}
+
+// Len returns the number of relabel configs in pcs.
+func (pcs *ParsedConfigs) Len() int {
+	if pcs == nil {
+		return 0
+	}
+	return len(pcs.prcs)
+}
+
+// String returns human-readabale representation for pcs.
+func (pcs *ParsedConfigs) String() string {
+	if pcs == nil {
+		return ""
+	}
+	var sb strings.Builder
+	for _, prc := range pcs.prcs {
+		fmt.Fprintf(&sb, "%s", prc.String())
+	}
+	return sb.String()
+}
+
 // LoadRelabelConfigs loads relabel configs from the given path.
-func LoadRelabelConfigs(path string) ([]ParsedRelabelConfig, error) {
+func LoadRelabelConfigs(path string) (*ParsedConfigs, error) {
 	data, err := ioutil.ReadFile(path)
 	if err != nil {
 		return nil, fmt.Errorf("cannot read `relabel_configs` from %q: %w", path, err)
 	}
 	data = envtemplate.Replace(data)
-	var rcs []RelabelConfig
-	if err := yaml.UnmarshalStrict(data, &rcs); err != nil {
+	pcs, err := ParseRelabelConfigsData(data)
+	if err != nil {
 		return nil, fmt.Errorf("cannot unmarshal `relabel_configs` from %q: %w", path, err)
 	}
-	return ParseRelabelConfigs(nil, rcs)
+	return pcs, nil
+}
+
+// ParseRelabelConfigsData parses relabel configs from the given data.
+func ParseRelabelConfigsData(data []byte) (*ParsedConfigs, error) {
+	var rcs []RelabelConfig
+	if err := yaml.UnmarshalStrict(data, &rcs); err != nil {
+		return nil, err
+	}
+	return ParseRelabelConfigs(rcs)
 }
 
 // ParseRelabelConfigs parses rcs to dst.
-func ParseRelabelConfigs(dst []ParsedRelabelConfig, rcs []RelabelConfig) ([]ParsedRelabelConfig, error) {
+func ParseRelabelConfigs(rcs []RelabelConfig) (*ParsedConfigs, error) {
 	if len(rcs) == 0 {
-		return dst, nil
+		return nil, nil
 	}
+	prcs := make([]*parsedRelabelConfig, len(rcs))
 	for i := range rcs {
-		var err error
-		dst, err = parseRelabelConfig(dst, &rcs[i])
+		prc, err := parseRelabelConfig(&rcs[i])
 		if err != nil {
-			return dst, fmt.Errorf("error when parsing `relabel_config` #%d: %w", i+1, err)
+			return nil, fmt.Errorf("error when parsing `relabel_config` #%d: %w", i+1, err)
 		}
+		prcs[i] = prc
 	}
-	return dst, nil
+	return &ParsedConfigs{
+		prcs: prcs,
+	}, nil
 }
 
-var defaultRegexForRelabelConfig = regexp.MustCompile("^(.*)$")
+var (
+	defaultOriginalRegexForRelabelConfig = regexp.MustCompile(".*")
+	defaultRegexForRelabelConfig         = regexp.MustCompile("^(.*)$")
+)
 
-func parseRelabelConfig(dst []ParsedRelabelConfig, rc *RelabelConfig) ([]ParsedRelabelConfig, error) {
+func parseRelabelConfig(rc *RelabelConfig) (*parsedRelabelConfig, error) {
 	sourceLabels := rc.SourceLabels
 	separator := ";"
 	if rc.Separator != nil {
@@ -62,6 +102,7 @@ func parseRelabelConfig(dst []ParsedRelabelConfig, rc *RelabelConfig) ([]ParsedR
 	}
 	targetLabel := rc.TargetLabel
 	regexCompiled := defaultRegexForRelabelConfig
+	regexOriginalCompiled := defaultOriginalRegexForRelabelConfig
 	if rc.Regex != nil {
 		regex := *rc.Regex
 		if rc.Action != "replace_all" && rc.Action != "labelmap_all" {
@@ -69,9 +110,14 @@ func parseRelabelConfig(dst []ParsedRelabelConfig, rc *RelabelConfig) ([]ParsedR
 		}
 		re, err := regexp.Compile(regex)
 		if err != nil {
-			return dst, fmt.Errorf("cannot parse `regex` %q: %w", regex, err)
+			return nil, fmt.Errorf("cannot parse `regex` %q: %w", regex, err)
 		}
 		regexCompiled = re
+		reOriginal, err := regexp.Compile(*rc.Regex)
+		if err != nil {
+			return nil, fmt.Errorf("cannot parse `regex` %q: %w", *rc.Regex, err)
+		}
+		regexOriginalCompiled = reOriginal
 	}
 	modulus := rc.Modulus
 	replacement := "$1"
@@ -85,49 +131,49 @@ func parseRelabelConfig(dst []ParsedRelabelConfig, rc *RelabelConfig) ([]ParsedR
 	switch action {
 	case "replace":
 		if targetLabel == "" {
-			return dst, fmt.Errorf("missing `target_label` for `action=replace`")
+			return nil, fmt.Errorf("missing `target_label` for `action=replace`")
 		}
 	case "replace_all":
 		if len(sourceLabels) == 0 {
-			return dst, fmt.Errorf("missing `source_labels` for `action=replace_all`")
+			return nil, fmt.Errorf("missing `source_labels` for `action=replace_all`")
 		}
 		if targetLabel == "" {
-			return dst, fmt.Errorf("missing `target_label` for `action=replace_all`")
+			return nil, fmt.Errorf("missing `target_label` for `action=replace_all`")
 		}
 	case "keep_if_equal":
 		if len(sourceLabels) < 2 {
-			return dst, fmt.Errorf("`source_labels` must contain at least two entries for `action=keep_if_equal`; got %q", sourceLabels)
+			return nil, fmt.Errorf("`source_labels` must contain at least two entries for `action=keep_if_equal`; got %q", sourceLabels)
 		}
 	case "drop_if_equal":
 		if len(sourceLabels) < 2 {
-			return dst, fmt.Errorf("`source_labels` must contain at least two entries for `action=drop_if_equal`; got %q", sourceLabels)
+			return nil, fmt.Errorf("`source_labels` must contain at least two entries for `action=drop_if_equal`; got %q", sourceLabels)
 		}
 	case "keep":
 		if len(sourceLabels) == 0 {
-			return dst, fmt.Errorf("missing `source_labels` for `action=keep`")
+			return nil, fmt.Errorf("missing `source_labels` for `action=keep`")
 		}
 	case "drop":
 		if len(sourceLabels) == 0 {
-			return dst, fmt.Errorf("missing `source_labels` for `action=drop`")
+			return nil, fmt.Errorf("missing `source_labels` for `action=drop`")
 		}
 	case "hashmod":
 		if len(sourceLabels) == 0 {
-			return dst, fmt.Errorf("missing `source_labels` for `action=hashmod`")
+			return nil, fmt.Errorf("missing `source_labels` for `action=hashmod`")
 		}
 		if targetLabel == "" {
-			return dst, fmt.Errorf("missing `target_label` for `action=hashmod`")
+			return nil, fmt.Errorf("missing `target_label` for `action=hashmod`")
 		}
 		if modulus < 1 {
-			return dst, fmt.Errorf("unexpected `modulus` for `action=hashmod`: %d; must be greater than 0", modulus)
+			return nil, fmt.Errorf("unexpected `modulus` for `action=hashmod`: %d; must be greater than 0", modulus)
 		}
 	case "labelmap":
 	case "labelmap_all":
 	case "labeldrop":
 	case "labelkeep":
 	default:
-		return dst, fmt.Errorf("unknown `action` %q", action)
+		return nil, fmt.Errorf("unknown `action` %q", action)
 	}
-	dst = append(dst, ParsedRelabelConfig{
+	return &parsedRelabelConfig{
 		SourceLabels: sourceLabels,
 		Separator:    separator,
 		TargetLabel:  targetLabel,
@@ -136,8 +182,8 @@ func parseRelabelConfig(dst []ParsedRelabelConfig, rc *RelabelConfig) ([]ParsedR
 		Replacement:  replacement,
 		Action:       action,
 
+		regexOriginal:                regexOriginalCompiled,
 		hasCaptureGroupInTargetLabel: strings.Contains(targetLabel, "$"),
 		hasCaptureGroupInReplacement: strings.Contains(replacement, "$"),
-	})
-	return dst, nil
+	}, nil
 }
diff --git a/lib/promrelabel/config_test.go b/lib/promrelabel/config_test.go
index 3a1ae1477c..f514d4d9aa 100644
--- a/lib/promrelabel/config_test.go
+++ b/lib/promrelabel/config_test.go
@@ -7,12 +7,12 @@ import (
 
 func TestLoadRelabelConfigsSuccess(t *testing.T) {
 	path := "testdata/relabel_configs_valid.yml"
-	prcs, err := LoadRelabelConfigs(path)
+	pcs, err := LoadRelabelConfigs(path)
 	if err != nil {
 		t.Fatalf("cannot load relabel configs from %q: %s", path, err)
 	}
-	if len(prcs) != 9 {
-		t.Fatalf("unexpected number of relabel configs loaded from %q; got %d; want %d", path, len(prcs), 9)
+	if n := pcs.Len(); n != 9 {
+		t.Fatalf("unexpected number of relabel configs loaded from %q; got %d; want %d", path, n, 9)
 	}
 }
 
@@ -23,7 +23,7 @@ func TestLoadRelabelConfigsFailure(t *testing.T) {
 		if err == nil {
 			t.Fatalf("expecting non-nil error")
 		}
-		if len(rcs) != 0 {
+		if rcs.Len() != 0 {
 			t.Fatalf("unexpected non-empty rcs: %#v", rcs)
 		}
 	}
@@ -36,14 +36,14 @@ func TestLoadRelabelConfigsFailure(t *testing.T) {
 }
 
 func TestParseRelabelConfigsSuccess(t *testing.T) {
-	f := func(rcs []RelabelConfig, prcsExpected []ParsedRelabelConfig) {
+	f := func(rcs []RelabelConfig, pcsExpected *ParsedConfigs) {
 		t.Helper()
-		prcs, err := ParseRelabelConfigs(nil, rcs)
+		pcs, err := ParseRelabelConfigs(rcs)
 		if err != nil {
 			t.Fatalf("unexected error: %s", err)
 		}
-		if !reflect.DeepEqual(prcs, prcsExpected) {
-			t.Fatalf("unexpected prcs; got\n%#v\nwant\n%#v", prcs, prcsExpected)
+		if !reflect.DeepEqual(pcs, pcsExpected) {
+			t.Fatalf("unexpected pcs; got\n%#v\nwant\n%#v", pcs, pcsExpected)
 		}
 	}
 	f(nil, nil)
@@ -52,16 +52,19 @@ func TestParseRelabelConfigsSuccess(t *testing.T) {
 			SourceLabels: []string{"foo", "bar"},
 			TargetLabel:  "xxx",
 		},
-	}, []ParsedRelabelConfig{
-		{
-			SourceLabels: []string{"foo", "bar"},
-			Separator:    ";",
-			TargetLabel:  "xxx",
-			Regex:        defaultRegexForRelabelConfig,
-			Replacement:  "$1",
-			Action:       "replace",
+	}, &ParsedConfigs{
+		prcs: []*parsedRelabelConfig{
+			{
+				SourceLabels: []string{"foo", "bar"},
+				Separator:    ";",
+				TargetLabel:  "xxx",
+				Regex:        defaultRegexForRelabelConfig,
+				Replacement:  "$1",
+				Action:       "replace",
 
-			hasCaptureGroupInReplacement: true,
+				regexOriginal:                defaultOriginalRegexForRelabelConfig,
+				hasCaptureGroupInReplacement: true,
+			},
 		},
 	})
 }
@@ -69,12 +72,12 @@ func TestParseRelabelConfigsSuccess(t *testing.T) {
 func TestParseRelabelConfigsFailure(t *testing.T) {
 	f := func(rcs []RelabelConfig) {
 		t.Helper()
-		prcs, err := ParseRelabelConfigs(nil, rcs)
+		pcs, err := ParseRelabelConfigs(rcs)
 		if err == nil {
 			t.Fatalf("expecting non-nil error")
 		}
-		if len(prcs) > 0 {
-			t.Fatalf("unexpected non-empty prcs: %#v", prcs)
+		if pcs.Len() > 0 {
+			t.Fatalf("unexpected non-empty pcs: %#v", pcs)
 		}
 	}
 	t.Run("invalid-regex", func(t *testing.T) {
diff --git a/lib/promrelabel/relabel.go b/lib/promrelabel/relabel.go
index 95cd0d9249..a161e55cc5 100644
--- a/lib/promrelabel/relabel.go
+++ b/lib/promrelabel/relabel.go
@@ -12,10 +12,10 @@ import (
 	xxhash "github.com/cespare/xxhash/v2"
 )
 
-// ParsedRelabelConfig contains parsed `relabel_config`.
+// parsedRelabelConfig contains parsed `relabel_config`.
 //
 // See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
-type ParsedRelabelConfig struct {
+type parsedRelabelConfig struct {
 	SourceLabels []string
 	Separator    string
 	TargetLabel  string
@@ -24,29 +24,32 @@ type ParsedRelabelConfig struct {
 	Replacement  string
 	Action       string
 
+	regexOriginal                *regexp.Regexp
 	hasCaptureGroupInTargetLabel bool
 	hasCaptureGroupInReplacement bool
 }
 
 // String returns human-readable representation for prc.
-func (prc *ParsedRelabelConfig) String() string {
+func (prc *parsedRelabelConfig) String() string {
 	return fmt.Sprintf("SourceLabels=%s, Separator=%s, TargetLabel=%s, Regex=%s, Modulus=%d, Replacement=%s, Action=%s",
 		prc.SourceLabels, prc.Separator, prc.TargetLabel, prc.Regex.String(), prc.Modulus, prc.Replacement, prc.Action)
 }
 
-// ApplyRelabelConfigs applies prcs to labels starting from the labelsOffset.
+// Apply applies pcs to labels starting from the labelsOffset.
 //
 // If isFinalize is set, then FinalizeLabels is called on the labels[labelsOffset:].
 //
 // The returned labels at labels[labelsOffset:] are sorted.
-func ApplyRelabelConfigs(labels []prompbmarshal.Label, labelsOffset int, prcs []ParsedRelabelConfig, isFinalize bool) []prompbmarshal.Label {
-	for i := range prcs {
-		tmp := applyRelabelConfig(labels, labelsOffset, &prcs[i])
-		if len(tmp) == labelsOffset {
-			// All the labels have been removed.
-			return tmp
+func (pcs *ParsedConfigs) Apply(labels []prompbmarshal.Label, labelsOffset int, isFinalize bool) []prompbmarshal.Label {
+	if pcs != nil {
+		for _, prc := range pcs.prcs {
+			tmp := prc.apply(labels, labelsOffset)
+			if len(tmp) == labelsOffset {
+				// All the labels have been removed.
+				return tmp
+			}
+			labels = tmp
 		}
-		labels = tmp
 	}
 	labels = removeEmptyLabels(labels, labelsOffset)
 	if isFinalize {
@@ -106,10 +109,10 @@ func FinalizeLabels(dst, src []prompbmarshal.Label) []prompbmarshal.Label {
 	return dst
 }
 
-// applyRelabelConfig applies relabeling according to prc.
+// apply applies relabeling according to prc.
 //
 // See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
-func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *ParsedRelabelConfig) []prompbmarshal.Label {
+func (prc *parsedRelabelConfig) apply(labels []prompbmarshal.Label, labelsOffset int) []prompbmarshal.Label {
 	src := labels[labelsOffset:]
 	switch prc.Action {
 	case "replace":
@@ -150,22 +153,13 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 	case "replace_all":
 		bb := relabelBufPool.Get()
 		bb.B = concatLabelValues(bb.B[:0], src, prc.SourceLabels, prc.Separator)
-		if prefix, complete := prc.Regex.LiteralPrefix(); complete && !prc.hasCaptureGroupInReplacement {
-			// Fast path - string replacement without regexp.
-			sourceStr := string(bb.B)
-			relabelBufPool.Put(bb)
-			valueStr := strings.ReplaceAll(sourceStr, prefix, prc.Replacement)
-			return setLabelValue(labels, labelsOffset, prc.TargetLabel, valueStr)
-		}
-		if !prc.Regex.Match(bb.B) {
-			// Fast path - nothing to replace.
-			relabelBufPool.Put(bb)
-			return labels
-		}
-		sourceStr := string(bb.B) // Make a copy of bb, since it can be returned from ReplaceAllString
+		sourceStr := string(bb.B)
 		relabelBufPool.Put(bb)
-		valueStr := prc.Regex.ReplaceAllString(sourceStr, prc.Replacement)
-		return setLabelValue(labels, labelsOffset, prc.TargetLabel, valueStr)
+		valueStr, ok := prc.replaceStringSubmatches(sourceStr, prc.Replacement, prc.hasCaptureGroupInReplacement)
+		if ok {
+			labels = setLabelValue(labels, labelsOffset, prc.TargetLabel, valueStr)
+		}
+		return labels
 	case "keep_if_equal":
 		// Keep the entry if all the label values in source_labels are equal.
 		// For example:
@@ -193,14 +187,7 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 	case "keep":
 		bb := relabelBufPool.Get()
 		bb.B = concatLabelValues(bb.B[:0], src, prc.SourceLabels, prc.Separator)
-		keep := false
-		if prefix, complete := prc.Regex.LiteralPrefix(); complete {
-			// Fast path - simple string match
-			keep = prefix == string(bb.B)
-		} else {
-			// Slow path - match by regexp
-			keep = prc.Regex.Match(bb.B)
-		}
+		keep := prc.matchString(bytesutil.ToUnsafeString(bb.B))
 		relabelBufPool.Put(bb)
 		if !keep {
 			return labels[:labelsOffset]
@@ -209,14 +196,7 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 	case "drop":
 		bb := relabelBufPool.Get()
 		bb.B = concatLabelValues(bb.B[:0], src, prc.SourceLabels, prc.Separator)
-		drop := false
-		if prefix, complete := prc.Regex.LiteralPrefix(); complete {
-			// Fast path - simple string match
-			drop = prefix == string(bb.B)
-		} else {
-			// Slow path - match by regexp
-			drop = prc.Regex.Match(bb.B)
-		}
+		drop := prc.matchString(bytesutil.ToUnsafeString(bb.B))
 		relabelBufPool.Put(bb)
 		if drop {
 			return labels[:labelsOffset]
@@ -232,42 +212,23 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 	case "labelmap":
 		for i := range src {
 			label := &src[i]
-			match := prc.Regex.FindStringSubmatchIndex(label.Name)
-			if match == nil {
-				continue
+			labelName, ok := prc.replaceFullString(label.Name, prc.Replacement, prc.hasCaptureGroupInReplacement)
+			if ok {
+				labels = setLabelValue(labels, labelsOffset, labelName, label.Value)
 			}
-			value := relabelBufPool.Get()
-			value.B = prc.Regex.ExpandString(value.B[:0], prc.Replacement, label.Name, match)
-			labelName := string(value.B)
-			relabelBufPool.Put(value)
-			labels = setLabelValue(labels, labelsOffset, labelName, label.Value)
 		}
 		return labels
 	case "labelmap_all":
 		for i := range src {
 			label := &src[i]
-			if prefix, complete := prc.Regex.LiteralPrefix(); complete && !prc.hasCaptureGroupInReplacement {
-				// Fast path - replace without regexp
-				label.Name = strings.ReplaceAll(label.Name, prefix, prc.Replacement)
-			} else {
-				// Slow path - replace with regexp.
-				if !prc.Regex.MatchString(label.Name) {
-					continue
-				}
-				label.Name = prc.Regex.ReplaceAllString(label.Name, prc.Replacement)
-			}
+			label.Name, _ = prc.replaceStringSubmatches(label.Name, prc.Replacement, prc.hasCaptureGroupInReplacement)
 		}
 		return labels
 	case "labeldrop":
 		keepSrc := true
 		for i := range src {
 			label := &src[i]
-			if prefix, complete := prc.Regex.LiteralPrefix(); complete {
-				if prefix == label.Name {
-					keepSrc = false
-					break
-				}
-			} else if prc.Regex.MatchString(label.Name) {
+			if prc.matchString(label.Name) {
 				keepSrc = false
 				break
 			}
@@ -278,11 +239,7 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 		dst := labels[:labelsOffset]
 		for i := range src {
 			label := &src[i]
-			if prefix, complete := prc.Regex.LiteralPrefix(); complete {
-				if prefix != label.Name {
-					dst = append(dst, *label)
-				}
-			} else if !prc.Regex.MatchString(label.Name) {
+			if !prc.matchString(label.Name) {
 				dst = append(dst, *label)
 			}
 		}
@@ -291,12 +248,7 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 		keepSrc := true
 		for i := range src {
 			label := &src[i]
-			if prefix, complete := prc.Regex.LiteralPrefix(); complete {
-				if prefix != label.Name {
-					keepSrc = false
-					break
-				}
-			} else if !prc.Regex.MatchString(src[i].Name) {
+			if !prc.matchString(label.Name) {
 				keepSrc = false
 				break
 			}
@@ -307,11 +259,7 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 		dst := labels[:labelsOffset]
 		for i := range src {
 			label := &src[i]
-			if prefix, complete := prc.Regex.LiteralPrefix(); complete {
-				if prefix == label.Name {
-					dst = append(dst, *label)
-				}
-			} else if prc.Regex.MatchString(label.Name) {
+			if prc.matchString(label.Name) {
 				dst = append(dst, *label)
 			}
 		}
@@ -322,7 +270,74 @@ func applyRelabelConfig(labels []prompbmarshal.Label, labelsOffset int, prc *Par
 	}
 }
 
-func (prc *ParsedRelabelConfig) expandCaptureGroups(template, source string, match []int) string {
+func (prc *parsedRelabelConfig) replaceFullString(s, replacement string, hasCaptureGroupInReplacement bool) (string, bool) {
+	prefix, complete := prc.regexOriginal.LiteralPrefix()
+	if complete && !hasCaptureGroupInReplacement {
+		if s == prefix {
+			return replacement, true
+		}
+		return s, false
+	}
+	if !strings.HasPrefix(s, prefix) {
+		return s, false
+	}
+	if replacement == "$1" {
+		// Fast path for commonly used rule for deleting label prefixes such as:
+		//
+		// - action: labelmap
+		//   regex: __meta_kubernetes_node_label_(.+)
+		//
+		reStr := prc.regexOriginal.String()
+		if strings.HasPrefix(reStr, prefix) {
+			suffix := s[len(prefix):]
+			reSuffix := reStr[len(prefix):]
+			switch reSuffix {
+			case "(.*)":
+				return suffix, true
+			case "(.+)":
+				if len(suffix) > 0 {
+					return suffix, true
+				}
+				return s, false
+			}
+		}
+	}
+	// Slow path - regexp processing
+	match := prc.Regex.FindStringSubmatchIndex(s)
+	if match == nil {
+		return s, false
+	}
+	bb := relabelBufPool.Get()
+	bb.B = prc.Regex.ExpandString(bb.B[:0], replacement, s, match)
+	result := string(bb.B)
+	relabelBufPool.Put(bb)
+	return result, true
+}
+
+func (prc *parsedRelabelConfig) replaceStringSubmatches(s, replacement string, hasCaptureGroupInReplacement bool) (string, bool) {
+	re := prc.regexOriginal
+	prefix, complete := re.LiteralPrefix()
+	if complete && !hasCaptureGroupInReplacement {
+		if !strings.Contains(s, prefix) {
+			return s, false
+		}
+		return strings.ReplaceAll(s, prefix, replacement), true
+	}
+	if !re.MatchString(s) {
+		return s, false
+	}
+	return re.ReplaceAllString(s, replacement), true
+}
+
+func (prc *parsedRelabelConfig) matchString(s string) bool {
+	prefix, complete := prc.regexOriginal.LiteralPrefix()
+	if complete {
+		return prefix == s
+	}
+	return strings.HasPrefix(s, prefix) && prc.Regex.MatchString(s)
+}
+
+func (prc *parsedRelabelConfig) expandCaptureGroups(template, source string, match []int) string {
 	bb := relabelBufPool.Get()
 	bb.B = prc.Regex.ExpandString(bb.B[:0], template, source, match)
 	s := string(bb.B)
diff --git a/lib/promrelabel/relabel_test.go b/lib/promrelabel/relabel_test.go
index 6185f029be..cc06887e7b 100644
--- a/lib/promrelabel/relabel_test.go
+++ b/lib/promrelabel/relabel_test.go
@@ -2,24 +2,27 @@ package promrelabel
 
 import (
 	"reflect"
-	"regexp"
 	"testing"
 
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
 )
 
 func TestApplyRelabelConfigs(t *testing.T) {
-	f := func(prcs []ParsedRelabelConfig, labels []prompbmarshal.Label, isFinalize bool, resultExpected []prompbmarshal.Label) {
+	f := func(config string, labels []prompbmarshal.Label, isFinalize bool, resultExpected []prompbmarshal.Label) {
 		t.Helper()
-		result := ApplyRelabelConfigs(labels, 0, prcs, isFinalize)
+		pcs, err := ParseRelabelConfigsData([]byte(config))
+		if err != nil {
+			t.Fatalf("cannot parse %q: %s", config, err)
+		}
+		result := pcs.Apply(labels, 0, isFinalize)
 		if !reflect.DeepEqual(result, resultExpected) {
 			t.Fatalf("unexpected result; got\n%v\nwant\n%v", result, resultExpected)
 		}
 	}
 	t.Run("empty_relabel_configs", func(t *testing.T) {
-		f(nil, nil, false, nil)
-		f(nil, nil, true, nil)
-		f(nil, []prompbmarshal.Label{
+		f("", nil, false, nil)
+		f("", nil, true, nil)
+		f("", []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "bar",
@@ -30,7 +33,7 @@ func TestApplyRelabelConfigs(t *testing.T) {
 				Value: "bar",
 			},
 		})
-		f(nil, []prompbmarshal.Label{
+		f("", []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "bar",
@@ -55,35 +58,20 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace-miss", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, nil, false, []prompbmarshal.Label{})
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"foo"},
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, nil, false, []prompbmarshal.Label{})
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"foo"},
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace
+  target_label: bar
+`, nil, false, []prompbmarshal.Label{})
+		f(`
+- action: replace
+  source_labels: ["foo"]
+  target_label: bar
+`, nil, false, []prompbmarshal.Label{})
+		f(`
+- action: replace
+  source_labels: ["foo"]
+  target_label: "bar"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -94,16 +82,12 @@ func TestApplyRelabelConfigs(t *testing.T) {
 				Value: "yyy",
 			},
 		})
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"foo"},
-				TargetLabel:                  "bar",
-				Regex:                        regexp.MustCompile(".+"),
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace
+  source_labels: ["foo"]
+  target_label: "bar"
+  regex: ".+"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -116,17 +100,12 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"xxx", "foo"},
-				Separator:                    ";",
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "a-$1-b",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace
+  source_labels: ["xxx", "foo"]
+  target_label: "bar"
+  replacement: "a-$1-b"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -143,18 +122,12 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace-hit-target-label-with-capture-group", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"xxx", "foo"},
-				Separator:                    ";",
-				TargetLabel:                  "bar-$1",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "a-$1-b",
-				hasCaptureGroupInTargetLabel: true,
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace
+  source_labels: ["xxx", "foo"]
+  target_label: "bar-$1"
+  replacement: "a-$1-b"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -171,35 +144,21 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace_all-miss", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace_all",
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, nil, false, []prompbmarshal.Label{})
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace_all",
-				SourceLabels:                 []string{"foo"},
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, nil, false, []prompbmarshal.Label{})
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace_all",
-				SourceLabels:                 []string{"foo"},
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace_all
+  source_labels: [foo]
+  target_label: "bar"
+`, nil, false, []prompbmarshal.Label{})
+		f(`
+- action: replace_all
+  source_labels: ["foo"]
+  target_label: "bar"
+`, nil, false, []prompbmarshal.Label{})
+		f(`
+- action: replace_all
+  source_labels: ["foo"]
+  target_label: "bar"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -210,16 +169,12 @@ func TestApplyRelabelConfigs(t *testing.T) {
 				Value: "yyy",
 			},
 		})
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace_all",
-				SourceLabels:                 []string{"foo"},
-				TargetLabel:                  "bar",
-				Regex:                        regexp.MustCompile(".+"),
-				Replacement:                  "$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace_all
+  source_labels: ["foo"]
+  target_label: "bar"
+  regex: ".+"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -232,16 +187,13 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace_all-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "replace_all",
-				SourceLabels: []string{"xxx"},
-				Separator:    ";",
-				TargetLabel:  "xxx",
-				Regex:        regexp.MustCompile("-"),
-				Replacement:  ".",
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace_all
+  source_labels: ["xxx"]
+  target_label: "xxx"
+  regex: "-"
+  replacement: "."
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "a-b-c",
@@ -254,17 +206,13 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace_all-regex-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace_all",
-				SourceLabels:                 []string{"xxx", "foo"},
-				Separator:                    ";",
-				TargetLabel:                  "xxx",
-				Regex:                        regexp.MustCompile("(;)"),
-				Replacement:                  "-$1-",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace_all
+  source_labels: ["xxx", "foo"]
+  target_label: "xxx"
+  regex: "(;)"
+  replacement: "-$1-"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "y;y",
@@ -277,24 +225,16 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace-add-multi-labels", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"xxx"},
-				TargetLabel:                  "bar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "a-$1",
-				hasCaptureGroupInReplacement: true,
-			},
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"bar"},
-				TargetLabel:                  "zar",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "b-$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace
+  source_labels: ["xxx"]
+  target_label: "bar"
+  replacement: "a-$1"
+- action: replace
+  source_labels: ["bar"]
+  target_label: "zar"
+  replacement: "b-$1"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -323,16 +263,12 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace-self", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:                       "replace",
-				SourceLabels:                 []string{"foo"},
-				TargetLabel:                  "foo",
-				Regex:                        defaultRegexForRelabelConfig,
-				Replacement:                  "a-$1",
-				hasCaptureGroupInReplacement: true,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: replace
+  source_labels: ["foo"]
+  target_label: "foo"
+  replacement: "a-$1"
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "aaxx",
@@ -345,14 +281,11 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("replace-missing-source", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:      "replace",
-				TargetLabel: "foo",
-				Regex:       defaultRegexForRelabelConfig,
-				Replacement: "foobar",
-			},
-		}, []prompbmarshal.Label{}, true, []prompbmarshal.Label{
+		f(`
+- action: replace
+  target_label: foo
+  replacement: "foobar"
+`, []prompbmarshal.Label{}, true, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "foobar",
@@ -360,18 +293,14 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("keep_if_equal-miss", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "keep_if_equal",
-				SourceLabels: []string{"foo", "bar"},
-			},
-		}, nil, true, nil)
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "keep_if_equal",
-				SourceLabels: []string{"xxx", "bar"},
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: keep_if_equal
+  source_labels: ["foo", "bar"]
+`, nil, true, nil)
+		f(`
+- action: keep_if_equal
+  source_labels: ["xxx", "bar"]
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -379,12 +308,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		}, true, []prompbmarshal.Label{})
 	})
 	t.Run("keep_if_equal-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "keep_if_equal",
-				SourceLabels: []string{"xxx", "bar"},
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: keep_if_equal
+  source_labels: ["xxx", "bar"]
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -405,18 +332,14 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("drop_if_equal-miss", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "drop_if_equal",
-				SourceLabels: []string{"foo", "bar"},
-			},
-		}, nil, true, nil)
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "drop_if_equal",
-				SourceLabels: []string{"xxx", "bar"},
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: drop_if_equal
+  source_labels: ["foo", "bar"]
+`, nil, true, nil)
+		f(`
+- action: drop_if_equal
+  source_labels: ["xxx", "bar"]
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -429,12 +352,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("drop_if_equal-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "drop_if_equal",
-				SourceLabels: []string{"xxx", "bar"},
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: drop_if_equal
+  source_labels: [xxx, bar]
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -446,20 +367,16 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		}, true, []prompbmarshal.Label{})
 	})
 	t.Run("keep-miss", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "keep",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile(".+"),
-			},
-		}, nil, true, nil)
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "keep",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile(".+"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: keep
+  source_labels: [foo]
+  regex: ".+"
+`, nil, true, nil)
+		f(`
+- action: keep
+  source_labels: [foo]
+  regex: ".+"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -467,13 +384,11 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		}, true, []prompbmarshal.Label{})
 	})
 	t.Run("keep-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "keep",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile("yyy"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: keep
+  source_labels: [foo]
+  regex: "yyy"
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "yyy",
@@ -486,13 +401,11 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("keep-hit-regexp", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "keep",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile(".+"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: keep
+  source_labels: ["foo"]
+  regex: ".+"
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "yyy",
@@ -505,20 +418,16 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("drop-miss", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile(".+"),
-			},
-		}, nil, false, nil)
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile(".+"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: drop
+  source_labels: [foo]
+  regex: ".+"
+`, nil, false, nil)
+		f(`
+- action: drop
+  source_labels: [foo]
+  regex: ".+"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -531,13 +440,11 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("drop-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile("yyy"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: drop
+  source_labels: [foo]
+  regex: yyy
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "yyy",
@@ -545,13 +452,11 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		}, true, []prompbmarshal.Label{})
 	})
 	t.Run("drop-hit-regexp", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"foo"},
-				Regex:        regexp.MustCompile(".+"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: drop
+  source_labels: [foo]
+  regex: ".+"
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "yyy",
@@ -559,14 +464,12 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		}, true, []prompbmarshal.Label{})
 	})
 	t.Run("hashmod-miss", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "hashmod",
-				SourceLabels: []string{"foo"},
-				TargetLabel:  "aaa",
-				Modulus:      123,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: hashmod
+  source_labels: [foo]
+  target_label: aaa
+  modulus: 123
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -583,14 +486,12 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("hashmod-hit", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:       "hashmod",
-				SourceLabels: []string{"foo"},
-				TargetLabel:  "aaa",
-				Modulus:      123,
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: hashmod
+  source_labels: [foo]
+  target_label: aaa
+  modulus: 123
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "yyy",
@@ -606,14 +507,97 @@ func TestApplyRelabelConfigs(t *testing.T) {
 			},
 		})
 	})
-	t.Run("labelmap", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
+	t.Run("labelmap-copy-label", func(t *testing.T) {
+		f(`
+- action: labelmap
+  regex: "foo"
+  replacement: "bar"
+`, []prompbmarshal.Label{
 			{
-				Action:      "labelmap",
-				Regex:       regexp.MustCompile("foo(.+)"),
-				Replacement: "$1-x",
+				Name:  "foo",
+				Value: "yyy",
 			},
-		}, []prompbmarshal.Label{
+			{
+				Name:  "foobar",
+				Value: "aaa",
+			},
+		}, true, []prompbmarshal.Label{
+			{
+				Name:  "bar",
+				Value: "yyy",
+			},
+			{
+				Name:  "foo",
+				Value: "yyy",
+			},
+			{
+				Name:  "foobar",
+				Value: "aaa",
+			},
+		})
+	})
+	t.Run("labelmap-remove-prefix-dot-star", func(t *testing.T) {
+		f(`
+- action: labelmap
+  regex: "foo(.*)"
+`, []prompbmarshal.Label{
+			{
+				Name:  "xoo",
+				Value: "yyy",
+			},
+			{
+				Name:  "foobar",
+				Value: "aaa",
+			},
+		}, true, []prompbmarshal.Label{
+			{
+				Name:  "bar",
+				Value: "aaa",
+			},
+			{
+				Name:  "foobar",
+				Value: "aaa",
+			},
+			{
+				Name:  "xoo",
+				Value: "yyy",
+			},
+		})
+	})
+	t.Run("labelmap-remove-prefix-dot-plus", func(t *testing.T) {
+		f(`
+- action: labelmap
+  regex: "foo(.+)"
+`, []prompbmarshal.Label{
+			{
+				Name:  "foo",
+				Value: "yyy",
+			},
+			{
+				Name:  "foobar",
+				Value: "aaa",
+			},
+		}, true, []prompbmarshal.Label{
+			{
+				Name:  "bar",
+				Value: "aaa",
+			},
+			{
+				Name:  "foo",
+				Value: "yyy",
+			},
+			{
+				Name:  "foobar",
+				Value: "aaa",
+			},
+		})
+	})
+	t.Run("labelmap-regex", func(t *testing.T) {
+		f(`
+- action: labelmap
+  regex: "foo(.+)"
+  replacement: "$1-x"
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo",
 				Value: "yyy",
@@ -638,13 +622,11 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("labelmap_all", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:      "labelmap_all",
-				Regex:       regexp.MustCompile(`\.`),
-				Replacement: "-",
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labelmap_all
+  regex: "\\."
+  replacement: "-"
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo.bar.baz",
 				Value: "yyy",
@@ -665,13 +647,11 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("labelmap_all-regexp", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action:      "labelmap_all",
-				Regex:       regexp.MustCompile(`ba(.)`),
-				Replacement: "${1}ss",
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labelmap_all
+  regex: "ba(.)"
+  replacement: "${1}ss"
+`, []prompbmarshal.Label{
 			{
 				Name:  "foo.bar.baz",
 				Value: "yyy",
@@ -692,12 +672,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("labeldrop", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("dropme"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labeldrop
+  regex: dropme
+`, []prompbmarshal.Label{
 			{
 				Name:  "aaa",
 				Value: "bbb",
@@ -708,12 +686,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 				Value: "bbb",
 			},
 		})
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("dropme"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labeldrop
+  regex: dropme
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -738,12 +714,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("labeldrop-regexp", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("dropme.*"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labeldrop
+  regex: "dropme.*"
+`, []prompbmarshal.Label{
 			{
 				Name:  "aaa",
 				Value: "bbb",
@@ -754,12 +728,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 				Value: "bbb",
 			},
 		})
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("dropme.*"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labeldrop
+  regex: "dropme.*"
+`, []prompbmarshal.Label{
 			{
 				Name:  "xxx",
 				Value: "yyy",
@@ -784,12 +756,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("labelkeep", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labelkeep",
-				Regex:  regexp.MustCompile("keepme"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labelkeep
+  regex: "keepme"
+`, []prompbmarshal.Label{
 			{
 				Name:  "keepme",
 				Value: "aaa",
@@ -800,12 +770,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 				Value: "aaa",
 			},
 		})
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labelkeep",
-				Regex:  regexp.MustCompile("keepme"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labelkeep
+  regex: keepme
+`, []prompbmarshal.Label{
 			{
 				Name:  "keepme",
 				Value: "aaa",
@@ -826,12 +794,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 		})
 	})
 	t.Run("labelkeep-regexp", func(t *testing.T) {
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labelkeep",
-				Regex:  regexp.MustCompile("keepme.*"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labelkeep
+  regex: "keepme.*"
+`, []prompbmarshal.Label{
 			{
 				Name:  "keepme",
 				Value: "aaa",
@@ -842,12 +808,10 @@ func TestApplyRelabelConfigs(t *testing.T) {
 				Value: "aaa",
 			},
 		})
-		f([]ParsedRelabelConfig{
-			{
-				Action: "labelkeep",
-				Regex:  regexp.MustCompile("keepme.*"),
-			},
-		}, []prompbmarshal.Label{
+		f(`
+- action: labelkeep
+  regex: "keepme.*"
+`, []prompbmarshal.Label{
 			{
 				Name:  "keepme",
 				Value: "aaa",
diff --git a/lib/promrelabel/relabel_timing_test.go b/lib/promrelabel/relabel_timing_test.go
index fb0a0207c2..4904bb0efe 100644
--- a/lib/promrelabel/relabel_timing_test.go
+++ b/lib/promrelabel/relabel_timing_test.go
@@ -2,7 +2,6 @@ package promrelabel
 
 import (
 	"fmt"
-	"regexp"
 	"testing"
 
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
@@ -10,15 +9,11 @@ import (
 
 func BenchmarkApplyRelabelConfigs(b *testing.B) {
 	b.Run("replace-label-copy", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "replace",
-				SourceLabels: []string{"id"},
-				TargetLabel:  "__name__",
-				Regex:        defaultRegexForRelabelConfig,
-				Replacement:  "$1",
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: replace
+  source_labels: [id]
+  target_label: __name__
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -35,7 +30,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -55,14 +50,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("replace-set-label", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:      "replace",
-				TargetLabel: "__name__",
-				Regex:       defaultRegexForRelabelConfig,
-				Replacement: "foobar",
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: replace
+  target_label: __name__
+  replacement: foobar
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -79,7 +71,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -99,14 +91,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("replace-add-label", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:      "replace",
-				TargetLabel: "aaa",
-				Regex:       defaultRegexForRelabelConfig,
-				Replacement: "foobar",
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: replace
+  target_label: aaa
+  replacement: foobar
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -119,7 +108,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 2 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 2, labels))
 				}
@@ -139,15 +128,12 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("replace-mismatch", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "replace",
-				SourceLabels: []string{"non-existing-label"},
-				TargetLabel:  "id",
-				Regex:        regexp.MustCompile("(foobar)-.*"),
-				Replacement:  "$1",
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: replace
+  source_labels: ["non-existing-label"]
+  target_label: id
+  regex: "(foobar)-.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -164,7 +150,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -184,15 +170,12 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("replace-match-regex", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "replace",
-				SourceLabels: []string{"id"},
-				TargetLabel:  "id",
-				Regex:        regexp.MustCompile("(foobar)-.*"),
-				Replacement:  "$1",
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: replace
+  source_labels: [id]
+  target_label: id
+  regex: "(foobar)-.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -209,7 +192,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -229,13 +212,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("drop-mismatch", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"non-existing-label"},
-				Regex:        regexp.MustCompile("(foobar)-.*"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: drop
+  source_labels: ["non-existing-label"]
+  regex: "(foobar)-.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -252,7 +233,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -272,13 +253,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("drop-match", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"id"},
-				Regex:        regexp.MustCompile("yes"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: drop
+  source_labels: [id]
+  regex: yes
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -295,7 +274,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 0 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 0, labels))
 				}
@@ -303,13 +282,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("drop-match-regexp", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"id"},
-				Regex:        regexp.MustCompile("(foobar)-.*"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: drop
+  source_labels: [id]
+  regex: "(foobar)-.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -326,7 +303,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 0 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 0, labels))
 				}
@@ -334,13 +311,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("keep-mismatch", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "keep",
-				SourceLabels: []string{"non-existing-label"},
-				Regex:        regexp.MustCompile("(foobar)-.*"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: keep
+  source_labels: ["non-existing-label"]
+  regex: "(foobar)-.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -357,7 +332,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 0 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 0, labels))
 				}
@@ -365,13 +340,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("keep-match", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "keep",
-				SourceLabels: []string{"id"},
-				Regex:        regexp.MustCompile("yes"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: keep
+  source_labels: [id]
+  regex: yes
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -388,7 +361,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -408,13 +381,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("keep-match-regexp", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "keep",
-				SourceLabels: []string{"id"},
-				Regex:        regexp.MustCompile("(foobar)-.*"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: keep
+  source_labels: [id]
+  regex: "(foobar)-.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -431,7 +402,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -451,12 +422,10 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("labeldrop-mismatch", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("non-existing-label"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: labeldrop
+  regex: "non-existing-label"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -473,7 +442,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -493,12 +462,10 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("labeldrop-match", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("id"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: labeldrop
+  regex: id
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -515,7 +482,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 1 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 1, labels))
 				}
@@ -529,12 +496,10 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("labeldrop-match-regexp", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("id.*"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: labeldrop
+  regex: "id.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -551,7 +516,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 1 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 1, labels))
 				}
@@ -565,12 +530,10 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("labelkeep-mismatch", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action: "labelkeep",
-				Regex:  regexp.MustCompile("non-existing-label"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: labelkeep
+  regex: "non-existing-label"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -587,7 +550,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 0 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 0, labels))
 				}
@@ -595,12 +558,10 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("labelkeep-match", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action: "labelkeep",
-				Regex:  regexp.MustCompile("id"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: labelkeep
+  regex: id
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -617,7 +578,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 1 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 1, labels))
 				}
@@ -631,12 +592,10 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 	b.Run("labelkeep-match-regexp", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action: "labelkeep",
-				Regex:  regexp.MustCompile("id.*"),
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: labelkeep
+  regex: "id.*"
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -653,7 +612,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != 1 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 1, labels))
 				}
@@ -666,19 +625,12 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			}
 		})
 	})
-	b.Run("labelmap", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:      "labelmap",
-				Regex:       regexp.MustCompile("a(.*)"),
-				Replacement: "$1",
-			},
-		}
+	b.Run("labelmap-mismatch", func(b *testing.B) {
+		pcs := mustParseRelabelConfigs(`
+- action: labelmap
+  regex: "a(.*)"
+`)
 		labelsOrig := []prompbmarshal.Label{
-			{
-				Name:  "aabc",
-				Value: "foobar-random-string-here",
-			},
 			{
 				Name:  "foo",
 				Value: "bar",
@@ -690,8 +642,38 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
-				if len(labels) != 3 {
+				labels = pcs.Apply(labels, 0, true)
+				if len(labels) != 1 {
+					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 3, labels))
+				}
+				if labels[0].Name != "foo" {
+					panic(fmt.Errorf("unexpected label name; got %q; want %q", labels[0].Name, "foo"))
+				}
+				if labels[0].Value != "bar" {
+					panic(fmt.Errorf("unexpected label value; got %q; want %q", labels[0].Value, "bar"))
+				}
+			}
+		})
+	})
+	b.Run("labelmap-match-remove-prefix", func(b *testing.B) {
+		pcs := mustParseRelabelConfigs(`
+- action: labelmap
+  regex: "a(.*)"
+`)
+		labelsOrig := []prompbmarshal.Label{
+			{
+				Name:  "aabc",
+				Value: "foobar-random-string-here",
+			},
+		}
+		b.ReportAllocs()
+		b.SetBytes(1)
+		b.RunParallel(func(pb *testing.PB) {
+			var labels []prompbmarshal.Label
+			for pb.Next() {
+				labels = append(labels[:0], labelsOrig...)
+				labels = pcs.Apply(labels, 0, true)
+				if len(labels) != 2 {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 3, labels))
 				}
 				if labels[0].Name != "aabc" {
@@ -706,24 +688,52 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 				if labels[1].Value != "foobar-random-string-here" {
 					panic(fmt.Errorf("unexpected label value; got %q; want %q", labels[1].Value, "foobar-random-string-here"))
 				}
-				if labels[2].Name != "foo" {
-					panic(fmt.Errorf("unexpected label name; got %q; want %q", labels[2].Name, "foo"))
+			}
+		})
+	})
+	b.Run("labelmap-match-regexp", func(b *testing.B) {
+		pcs := mustParseRelabelConfigs(`
+- action: labelmap
+  regex: "(.*)bc"
+`)
+		labelsOrig := []prompbmarshal.Label{
+			{
+				Name:  "aabc",
+				Value: "foobar-random-string-here",
+			},
+		}
+		b.ReportAllocs()
+		b.SetBytes(1)
+		b.RunParallel(func(pb *testing.PB) {
+			var labels []prompbmarshal.Label
+			for pb.Next() {
+				labels = append(labels[:0], labelsOrig...)
+				labels = pcs.Apply(labels, 0, true)
+				if len(labels) != 2 {
+					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), 3, labels))
 				}
-				if labels[2].Value != "bar" {
-					panic(fmt.Errorf("unexpected label value; got %q; want %q", labels[2].Value, "bar"))
+				if labels[0].Name != "aa" {
+					panic(fmt.Errorf("unexpected label name; got %q; want %q", labels[0].Name, "aa"))
+				}
+				if labels[0].Value != "foobar-random-string-here" {
+					panic(fmt.Errorf("unexpected label value; got %q; want %q", labels[0].Value, "foobar-random-string-here"))
+				}
+				if labels[1].Name != "aabc" {
+					panic(fmt.Errorf("unexpected label name; got %q; want %q", labels[1].Name, "aabc"))
+				}
+				if labels[1].Value != "foobar-random-string-here" {
+					panic(fmt.Errorf("unexpected label value; got %q; want %q", labels[1].Value, "foobar-random-string-here"))
 				}
 			}
 		})
 	})
 	b.Run("hashmod", func(b *testing.B) {
-		prcs := []ParsedRelabelConfig{
-			{
-				Action:       "hashmod",
-				SourceLabels: []string{"id"},
-				TargetLabel:  "id",
-				Modulus:      23,
-			},
-		}
+		pcs := mustParseRelabelConfigs(`
+- action: hashmod
+  source_labels: [id]
+  target_label: id
+  modulus: 23
+`)
 		labelsOrig := []prompbmarshal.Label{
 			{
 				Name:  "__name__",
@@ -740,7 +750,7 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 			var labels []prompbmarshal.Label
 			for pb.Next() {
 				labels = append(labels[:0], labelsOrig...)
-				labels = ApplyRelabelConfigs(labels, 0, prcs, true)
+				labels = pcs.Apply(labels, 0, true)
 				if len(labels) != len(labelsOrig) {
 					panic(fmt.Errorf("unexpected number of labels; got %d; want %d; labels:\n%#v", len(labels), len(labelsOrig), labels))
 				}
@@ -760,3 +770,11 @@ func BenchmarkApplyRelabelConfigs(b *testing.B) {
 		})
 	})
 }
+
+func mustParseRelabelConfigs(config string) *ParsedConfigs {
+	pcs, err := ParseRelabelConfigsData([]byte(config))
+	if err != nil {
+		panic(fmt.Errorf("unexpected error: %w", err))
+	}
+	return pcs
+}
diff --git a/lib/promscrape/config.go b/lib/promscrape/config.go
index 6c1e2f5026..4f97506b68 100644
--- a/lib/promscrape/config.go
+++ b/lib/promscrape/config.go
@@ -482,13 +482,11 @@ func getScrapeWorkConfig(sc *ScrapeConfig, baseDir string, globalCfg *GlobalConf
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse auth config for `job_name` %q: %w", jobName, err)
 	}
-	var relabelConfigs []promrelabel.ParsedRelabelConfig
-	relabelConfigs, err = promrelabel.ParseRelabelConfigs(relabelConfigs[:0], sc.RelabelConfigs)
+	relabelConfigs, err := promrelabel.ParseRelabelConfigs(sc.RelabelConfigs)
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse `relabel_configs` for `job_name` %q: %w", jobName, err)
 	}
-	var metricRelabelConfigs []promrelabel.ParsedRelabelConfig
-	metricRelabelConfigs, err = promrelabel.ParseRelabelConfigs(metricRelabelConfigs[:0], sc.MetricRelabelConfigs)
+	metricRelabelConfigs, err := promrelabel.ParseRelabelConfigs(sc.MetricRelabelConfigs)
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse `metric_relabel_configs` for `job_name` %q: %w", jobName, err)
 	}
@@ -527,8 +525,8 @@ type scrapeWorkConfig struct {
 	honorLabels          bool
 	honorTimestamps      bool
 	externalLabels       map[string]string
-	relabelConfigs       []promrelabel.ParsedRelabelConfig
-	metricRelabelConfigs []promrelabel.ParsedRelabelConfig
+	relabelConfigs       *promrelabel.ParsedConfigs
+	metricRelabelConfigs *promrelabel.ParsedConfigs
 	sampleLimit          int
 	disableCompression   bool
 	disableKeepAlive     bool
@@ -695,7 +693,7 @@ func appendScrapeWork(dst []*ScrapeWork, swc *scrapeWorkConfig, target string, e
 		// Reduce memory usage by interning all the strings in originalLabels.
 		internLabelStrings(originalLabels)
 	}
-	labels = promrelabel.ApplyRelabelConfigs(labels, 0, swc.relabelConfigs, false)
+	labels = swc.relabelConfigs.Apply(labels, 0, false)
 	labels = promrelabel.RemoveMetaLabels(labels[:0], labels)
 	// Remove references to already deleted labels, so GC could clean strings for label name and label value past len(labels).
 	// This should reduce memory usage when relabeling creates big number of temporary labels with long names and/or values.
diff --git a/lib/promscrape/config_test.go b/lib/promscrape/config_test.go
index a1dbc5f571..f2273ccc4b 100644
--- a/lib/promscrape/config_test.go
+++ b/lib/promscrape/config_test.go
@@ -4,13 +4,11 @@ import (
 	"crypto/tls"
 	"fmt"
 	"reflect"
-	"regexp"
 	"testing"
 	"time"
 
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
-	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
 )
 
 func TestLoadStaticConfigs(t *testing.T) {
@@ -1034,13 +1032,6 @@ scrape_configs:
 		},
 	})
 
-	prcs, err := promrelabel.ParseRelabelConfigs(nil, []promrelabel.RelabelConfig{{
-		SourceLabels: []string{"foo"},
-		TargetLabel:  "abc",
-	}})
-	if err != nil {
-		t.Fatalf("unexpected error when parsing relabel configs: %s", err)
-	}
 	f(`
 scrape_configs:
 - job_name: foo
@@ -1076,9 +1067,12 @@ scrape_configs:
 					Value: "foo",
 				},
 			},
-			AuthConfig:           &promauth.Config{},
-			MetricRelabelConfigs: prcs,
-			jobNameOriginal:      "foo",
+			AuthConfig: &promauth.Config{},
+			MetricRelabelConfigs: mustParseRelabelConfigs(`
+- source_labels: [foo]
+  target_label: abc
+`),
+			jobNameOriginal: "foo",
 		},
 	})
 	f(`
@@ -1374,8 +1368,6 @@ scrape_configs:
 	})
 }
 
-var defaultRegexForRelabelConfig = regexp.MustCompile("^(.*)$")
-
 func equalStaticConfigForScrapeWorks(a, b []*ScrapeWork) bool {
 	if len(a) != len(b) {
 		return false
diff --git a/lib/promscrape/scrapework.go b/lib/promscrape/scrapework.go
index adff00c2c5..313734d6b5 100644
--- a/lib/promscrape/scrapework.go
+++ b/lib/promscrape/scrapework.go
@@ -6,7 +6,6 @@ import (
 	"math"
 	"math/bits"
 	"strconv"
-	"strings"
 	"sync"
 	"time"
 
@@ -76,7 +75,7 @@ type ScrapeWork struct {
 	ProxyURL proxy.URL
 
 	// Optional `metric_relabel_configs`.
-	MetricRelabelConfigs []promrelabel.ParsedRelabelConfig
+	MetricRelabelConfigs *promrelabel.ParsedConfigs
 
 	// The maximum number of metrics to scrape after relabeling.
 	SampleLimit int
@@ -105,18 +104,10 @@ func (sw *ScrapeWork) key() string {
 	key := fmt.Sprintf("ScrapeURL=%s, ScrapeInterval=%s, ScrapeTimeout=%s, HonorLabels=%v, HonorTimestamps=%v, Labels=%s, "+
 		"AuthConfig=%s, MetricRelabelConfigs=%s, SampleLimit=%d, DisableCompression=%v, DisableKeepAlive=%v, StreamParse=%v, ScrapeAlignInterval=%s",
 		sw.ScrapeURL, sw.ScrapeInterval, sw.ScrapeTimeout, sw.HonorLabels, sw.HonorTimestamps, sw.LabelsString(),
-		sw.AuthConfig.String(), sw.metricRelabelConfigsString(), sw.SampleLimit, sw.DisableCompression, sw.DisableKeepAlive, sw.StreamParse, sw.ScrapeAlignInterval)
+		sw.AuthConfig.String(), sw.MetricRelabelConfigs.String(), sw.SampleLimit, sw.DisableCompression, sw.DisableKeepAlive, sw.StreamParse, sw.ScrapeAlignInterval)
 	return key
 }
 
-func (sw *ScrapeWork) metricRelabelConfigsString() string {
-	var sb strings.Builder
-	for _, prc := range sw.MetricRelabelConfigs {
-		fmt.Fprintf(&sb, "%s", prc.String())
-	}
-	return sb.String()
-}
-
 // Job returns job for the ScrapeWork
 func (sw *ScrapeWork) Job() string {
 	return promrelabel.GetLabelValueByName(sw.Labels, "job")
@@ -503,7 +494,7 @@ func (sw *scrapeWork) addRowToTimeseries(wc *writeRequestCtx, r *parser.Row, tim
 	labelsLen := len(wc.labels)
 	wc.labels = appendLabels(wc.labels, r.Metric, r.Tags, sw.Config.Labels, sw.Config.HonorLabels)
 	if needRelabel {
-		wc.labels = promrelabel.ApplyRelabelConfigs(wc.labels, labelsLen, sw.Config.MetricRelabelConfigs, true)
+		wc.labels = sw.Config.MetricRelabelConfigs.Apply(wc.labels, labelsLen, true)
 	} else {
 		wc.labels = promrelabel.FinalizeLabels(wc.labels[:labelsLen], wc.labels[labelsLen:])
 		promrelabel.SortLabels(wc.labels[labelsLen:])
diff --git a/lib/promscrape/scrapework_test.go b/lib/promscrape/scrapework_test.go
index 3e9fb95774..74b6f67e8e 100644
--- a/lib/promscrape/scrapework_test.go
+++ b/lib/promscrape/scrapework_test.go
@@ -2,7 +2,6 @@ package promscrape
 
 import (
 	"fmt"
-	"regexp"
 	"strings"
 	"testing"
 
@@ -102,7 +101,8 @@ func TestScrapeWorkScrapeInternalSuccess(t *testing.T) {
 		sw.PushData = func(wr *prompbmarshal.WriteRequest) {
 			pushDataCalls++
 			if len(wr.Timeseries) > len(timeseriesExpected) {
-				pushDataErr = fmt.Errorf("too many time series obtained; got %d; want %d", len(wr.Timeseries), len(timeseriesExpected))
+				pushDataErr = fmt.Errorf("too many time series obtained; got %d; want %d\ngot\n%+v\nwant\n%+v",
+					len(wr.Timeseries), len(timeseriesExpected), wr.Timeseries, timeseriesExpected)
 				return
 			}
 			tsExpected := timeseriesExpected[:len(wr.Timeseries)]
@@ -271,20 +271,14 @@ func TestScrapeWorkScrapeInternalSuccess(t *testing.T) {
 				Value: "foo.com",
 			},
 		},
-		MetricRelabelConfigs: []promrelabel.ParsedRelabelConfig{
-			{
-				SourceLabels: []string{"__address__", "job"},
-				Separator:    "/",
-				TargetLabel:  "instance",
-				Regex:        defaultRegexForRelabelConfig,
-				Replacement:  "$1",
-				Action:       "replace",
-			},
-			{
-				Action: "labeldrop",
-				Regex:  regexp.MustCompile("^c$"),
-			},
-		},
+		MetricRelabelConfigs: mustParseRelabelConfigs(`
+- action: replace
+  source_labels: ["__address__", "job"]
+  separator: "/"
+  target_label: "instance"
+- action: labeldrop
+  regex: c
+`),
 	}, `
 		foo{bar="baz",job="xx",instance="foo.com/xx"} 34.44 123
 		bar{a="b",job="xx",instance="foo.com/xx"} -3e4 123
@@ -311,18 +305,15 @@ func TestScrapeWorkScrapeInternalSuccess(t *testing.T) {
 				Value: "foo.com",
 			},
 		},
-		MetricRelabelConfigs: []promrelabel.ParsedRelabelConfig{
-			{
-				Action:       "drop",
-				SourceLabels: []string{"a", "c"},
-				Regex:        regexp.MustCompile("^bd$"),
-			},
-			{
-				Action:       "drop",
-				SourceLabels: []string{"__name__"},
-				Regex:        regexp.MustCompile("^(dropme|up)$"),
-			},
-		},
+		MetricRelabelConfigs: mustParseRelabelConfigs(`
+- action: drop
+  separator: ""
+  source_labels: [a, c]
+  regex: "^bd$"
+- action: drop
+  source_labels: [__name__]
+  regex: "dropme|up"
+`),
 	}, `
 		foo{bar="baz",job="xx",instance="foo.com"} 34.44 123
 		up{job="xx",instance="foo.com"} 1 123
@@ -440,3 +431,11 @@ func timeseriesToString(ts *prompbmarshal.TimeSeries) string {
 	fmt.Fprintf(&sb, "%g %d", s.Value, s.Timestamp)
 	return sb.String()
 }
+
+func mustParseRelabelConfigs(config string) *promrelabel.ParsedConfigs {
+	pcs, err := promrelabel.ParseRelabelConfigsData([]byte(config))
+	if err != nil {
+		panic(fmt.Errorf("cannot parse %q: %w", config, err))
+	}
+	return pcs
+}