[PERF] PromQL: Don't wrap matrix selectors as time-invariant

Matrix selectors have a Timestamp which indicates they are time-invariant,
so we don't need to wrap and then unwrap them when we come to use them.

Fix up tests that check this level of detail.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
Bryan Boreham 2025-07-19 16:11:00 +01:00
parent b290e0ec17
commit 94d3cac4ea
2 changed files with 54 additions and 47 deletions

View File

@ -1781,8 +1781,7 @@ func (ev *evaluator) eval(ctx context.Context, expr parser.Expr) (parser.Value,
} }
unwrapParenExpr(&e.Args[matrixArgIndex]) unwrapParenExpr(&e.Args[matrixArgIndex])
arg := unwrapStepInvariantExpr(e.Args[matrixArgIndex]) arg := e.Args[matrixArgIndex]
unwrapParenExpr(&arg)
sel := arg.(*parser.MatrixSelector) sel := arg.(*parser.MatrixSelector)
selVS := sel.VectorSelector.(*parser.VectorSelector) selVS := sel.VectorSelector.(*parser.VectorSelector)
@ -3794,7 +3793,9 @@ func preprocessExprHelper(expr parser.Expr, start, end time.Time) (isStepInvaria
return false, false return false, false
case *parser.MatrixSelector: case *parser.MatrixSelector:
return preprocessExprHelper(n.VectorSelector, start, end) // We don't need to wrap a MatrixSelector because functions over range vectors evaluate those directly.
isStepInvariant, _ := preprocessExprHelper(n.VectorSelector, start, end)
return isStepInvariant, false
case *parser.SubqueryExpr: case *parser.SubqueryExpr:
// Since we adjust offset for the @ modifier evaluation, // Since we adjust offset for the @ modifier evaluation,

View File

@ -2423,23 +2423,21 @@ func TestPreprocessAndWrapWithStepInvariantExpr(t *testing.T) {
}, },
{ {
input: `test{a="b"}[5y] @ 1603774699`, input: `test{a="b"}[5y] @ 1603774699`,
expected: &parser.StepInvariantExpr{ expected: &parser.MatrixSelector{
Expr: &parser.MatrixSelector{ VectorSelector: &parser.VectorSelector{
VectorSelector: &parser.VectorSelector{ Name: "test",
Name: "test", Timestamp: makeInt64Pointer(1603774699000),
Timestamp: makeInt64Pointer(1603774699000), LabelMatchers: []*labels.Matcher{
LabelMatchers: []*labels.Matcher{ parser.MustLabelMatcher(labels.MatchEqual, "a", "b"),
parser.MustLabelMatcher(labels.MatchEqual, "a", "b"), parser.MustLabelMatcher(labels.MatchEqual, "__name__", "test"),
parser.MustLabelMatcher(labels.MatchEqual, "__name__", "test"), },
}, PosRange: posrange.PositionRange{
PosRange: posrange.PositionRange{ Start: 0,
Start: 0, End: 11,
End: 11,
},
}, },
Range: 5 * 365 * 24 * time.Hour,
EndPos: 28,
}, },
Range: 5 * 365 * 24 * time.Hour,
EndPos: 28,
}, },
}, },
{ {
@ -2938,45 +2936,53 @@ func TestPreprocessAndWrapWithStepInvariantExpr(t *testing.T) {
}, },
}, },
{ {
input: `test[5y] @ start()`, input: `sum_over_time(test[5y] @ start())`,
expected: &parser.StepInvariantExpr{ expected: &parser.StepInvariantExpr{
Expr: &parser.MatrixSelector{ Expr: &parser.Call{
VectorSelector: &parser.VectorSelector{ Func: &parser.Function{
Name: "test", Name: "sum_over_time",
Timestamp: makeInt64Pointer(timestamp.FromTime(startTime)), ArgTypes: []parser.ValueType{parser.ValueTypeMatrix},
StartOrEnd: parser.START, ReturnType: parser.ValueTypeVector,
LabelMatchers: []*labels.Matcher{ },
parser.MustLabelMatcher(labels.MatchEqual, "__name__", "test"), Args: parser.Expressions{
}, &parser.MatrixSelector{
PosRange: posrange.PositionRange{ VectorSelector: &parser.VectorSelector{
Start: 0, Name: "test",
End: 4, Timestamp: makeInt64Pointer(timestamp.FromTime(startTime)),
StartOrEnd: parser.START,
LabelMatchers: []*labels.Matcher{
parser.MustLabelMatcher(labels.MatchEqual, "__name__", "test"),
},
PosRange: posrange.PositionRange{
Start: 14,
End: 18,
},
},
Range: 5 * 365 * 24 * time.Hour,
EndPos: 32,
}, },
}, },
Range: 5 * 365 * 24 * time.Hour, PosRange: posrange.PositionRange{Start: 0, End: 33},
EndPos: 18,
}, },
}, },
}, },
{ {
input: `test[5y] @ end()`, input: `test[5y] @ end()`,
expected: &parser.StepInvariantExpr{ expected: &parser.MatrixSelector{
Expr: &parser.MatrixSelector{ VectorSelector: &parser.VectorSelector{
VectorSelector: &parser.VectorSelector{ Name: "test",
Name: "test", Timestamp: makeInt64Pointer(timestamp.FromTime(endTime)),
Timestamp: makeInt64Pointer(timestamp.FromTime(endTime)), StartOrEnd: parser.END,
StartOrEnd: parser.END, LabelMatchers: []*labels.Matcher{
LabelMatchers: []*labels.Matcher{ parser.MustLabelMatcher(labels.MatchEqual, "__name__", "test"),
parser.MustLabelMatcher(labels.MatchEqual, "__name__", "test"), },
}, PosRange: posrange.PositionRange{
PosRange: posrange.PositionRange{ Start: 0,
Start: 0, End: 4,
End: 4,
},
}, },
Range: 5 * 365 * 24 * time.Hour,
EndPos: 16,
}, },
Range: 5 * 365 * 24 * time.Hour,
EndPos: 16,
}, },
}, },
{ {