Skip to content

Commit 08dd182

Browse files
committed
bench(ruler): add benchmark for select merging query reduction
1 parent 970f42b commit 08dd182

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package ruler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sync/atomic"
7+
"testing"
8+
"time"
9+
10+
"github.com/prometheus/prometheus/model/labels"
11+
"github.com/prometheus/prometheus/promql"
12+
"github.com/prometheus/prometheus/promql/parser"
13+
"github.com/prometheus/prometheus/rules"
14+
)
15+
16+
// BenchmarkSelectMerger simulates 114 rules (38 metrics × 3 deploy_color variants)
17+
// and compares query count with vs without merging.
18+
func BenchmarkSelectMerger(b *testing.B) {
19+
const (
20+
numMetrics = 38
21+
numColors = 3
22+
seriesPer = 50
23+
)
24+
colors := []string{"blue", "green", "canary"}
25+
26+
// Build 114 rules: 38 metrics × 3 deploy_color variants.
27+
rls := make([]rules.Rule, 0, numMetrics*numColors)
28+
for i := range numMetrics {
29+
for _, c := range colors {
30+
expr := fmt.Sprintf(`sum(metric_%d{deploy_color="%s",job="svc"})`, i, c)
31+
e, err := parser.ParseExpr(expr)
32+
if err != nil {
33+
b.Fatal(err)
34+
}
35+
rls = append(rls, &fakeRule{expr: e})
36+
}
37+
}
38+
39+
// Mock QueryFunc: returns seriesPer samples with varying deploy_color.
40+
mockQueryFunc := func(_ context.Context, qs string, _ time.Time) (promql.Vector, error) {
41+
vec := make(promql.Vector, seriesPer)
42+
for i := range vec {
43+
vec[i] = promql.Sample{
44+
Metric: labels.FromStrings(
45+
"__name__", "metric_0",
46+
"deploy_color", colors[i%numColors],
47+
"job", "svc",
48+
"instance", fmt.Sprintf("host-%d", i),
49+
),
50+
T: 0,
51+
F: float64(i),
52+
}
53+
}
54+
return vec, nil
55+
}
56+
57+
ts := time.Now()
58+
ctx := context.Background()
59+
60+
b.Run("without_merging", func(b *testing.B) {
61+
var calls atomic.Int64
62+
qf := func(ctx context.Context, qs string, t time.Time) (promql.Vector, error) {
63+
calls.Add(1)
64+
return mockQueryFunc(ctx, qs, t)
65+
}
66+
for b.Loop() {
67+
calls.Store(0)
68+
for _, r := range rls {
69+
_, err := qf(ctx, r.Query().String(), ts)
70+
if err != nil {
71+
b.Fatal(err)
72+
}
73+
}
74+
}
75+
b.ReportMetric(float64(calls.Load()), "queries/op")
76+
})
77+
78+
b.Run("with_merging", func(b *testing.B) {
79+
plan := planMergedSelects(rls, 2)
80+
var calls atomic.Int64
81+
qf := func(ctx context.Context, qs string, t time.Time) (promql.Vector, error) {
82+
calls.Add(1)
83+
return mockQueryFunc(ctx, qs, t)
84+
}
85+
for b.Loop() {
86+
calls.Store(0)
87+
cache := executePrefetch(ctx, plan, qf, ts)
88+
cached := cachedQueryFunc(qf, cache)
89+
for _, r := range rls {
90+
_, err := cached(ctx, r.Query().String(), ts)
91+
if err != nil {
92+
b.Fatal(err)
93+
}
94+
}
95+
}
96+
b.ReportMetric(float64(calls.Load()), "queries/op")
97+
})
98+
}

0 commit comments

Comments
 (0)