From 2c382f5e24e87aa7180c92c895741028da21b0e9 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 23 Dec 2022 12:40:22 +0000 Subject: [PATCH 1/3] promql: extract function to initialize LabelBuilder Signed-off-by: Bryan Boreham --- promql/engine.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/promql/engine.go b/promql/engine.go index 0455779a4b..a6fc29540d 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -1032,6 +1032,14 @@ type EvalNodeHelper struct { resultMetric map[string]labels.Labels } +func (enh *EvalNodeHelper) resetBuilder(lbls labels.Labels) { + if enh.lb == nil { + enh.lb = labels.NewBuilder(lbls) + } else { + enh.lb.Reset(lbls) + } +} + // DropMetricName is a cached version of DropMetricName. func (enh *EvalNodeHelper) DropMetricName(l labels.Labels) labels.Labels { if enh.Dmn == nil { @@ -2152,12 +2160,7 @@ func resultMetric(lhs, rhs labels.Labels, op parser.ItemType, matching *parser.V enh.resultMetric = make(map[string]labels.Labels, len(enh.Out)) } - if enh.lb == nil { - enh.lb = labels.NewBuilder(lhs) - } else { - enh.lb.Reset(lhs) - } - + enh.resetBuilder(lhs) buf := bytes.NewBuffer(enh.lblResultBuf[:0]) enh.lblBuf = lhs.Bytes(enh.lblBuf) buf.Write(enh.lblBuf) From aafef011b748c47e78b72ed1d7c40bb8cd31b369 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 23 Dec 2022 12:59:02 +0000 Subject: [PATCH 2/3] Promql: reuse LabelBuilder in aggregations We have a LabelBuilder in EvalNodeHelper; use it instead of creating a new one at every step. Need to take some care that different uses of enh.lb do not overlap. Signed-off-by: Bryan Boreham --- promql/engine.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/promql/engine.go b/promql/engine.go index a6fc29540d..fd20222076 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -2360,15 +2360,14 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without } } - lb := labels.NewBuilder(labels.EmptyLabels()) var buf []byte for si, s := range vec { metric := s.Metric if op == parser.COUNT_VALUES { - lb.Reset(metric) - lb.Set(valueLabel, strconv.FormatFloat(s.V, 'f', -1, 64)) - metric = lb.Labels(labels.EmptyLabels()) + enh.resetBuilder(metric) + enh.lb.Set(valueLabel, strconv.FormatFloat(s.V, 'f', -1, 64)) + metric = enh.lb.Labels(labels.EmptyLabels()) // We've changed the metric so we have to recompute the grouping key. recomputeGroupingKey = true @@ -2385,14 +2384,14 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without group, ok := result[groupingKey] // Add a new group if it doesn't exist. if !ok { - lb.Reset(metric) + enh.resetBuilder(metric) if without { - lb.Del(grouping...) - lb.Del(labels.MetricName) + enh.lb.Del(grouping...) + enh.lb.Del(labels.MetricName) } else { - lb.Keep(grouping...) + enh.lb.Keep(grouping...) } - m := lb.Labels(labels.EmptyLabels()) + m := enh.lb.Labels(labels.EmptyLabels()) newAgg := &groupedAggregation{ labels: m, value: s.V, From 1b0a29701b02202f192d2cb0c8b1ebaafc791f6a Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 23 Dec 2022 13:33:14 +0000 Subject: [PATCH 3/3] promql: optimise aggregation with no labels For a query like 'sum (foo)', we can quickly skip to the empty labels that its result needs. Signed-off-by: Bryan Boreham --- promql/engine.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/promql/engine.go b/promql/engine.go index fd20222076..ddfb26b13f 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -2384,14 +2384,18 @@ func (ev *evaluator) aggregation(op parser.ItemType, grouping []string, without group, ok := result[groupingKey] // Add a new group if it doesn't exist. if !ok { + var m labels.Labels enh.resetBuilder(metric) if without { enh.lb.Del(grouping...) enh.lb.Del(labels.MetricName) - } else { + m = enh.lb.Labels(labels.EmptyLabels()) + } else if len(grouping) > 0 { enh.lb.Keep(grouping...) + m = enh.lb.Labels(labels.EmptyLabels()) + } else { + m = labels.EmptyLabels() } - m := enh.lb.Labels(labels.EmptyLabels()) newAgg := &groupedAggregation{ labels: m, value: s.V,