Short-circuit vector binary ops (#9362)

In degenerate cases we can save the effort of building a map.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
Bryan Boreham 2021-09-21 13:07:36 +01:00 committed by GitHub
parent c4942ef3b7
commit 5a754bc043
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 0 deletions

View File

@ -130,6 +130,9 @@ func BenchmarkRangeQuery(b *testing.B) {
{
expr: "a_X unless b_X{l=~'.*[0-4]$'}",
},
{
expr: "a_X and b_X{l='notfound'}",
},
// Simple functions.
{
expr: "abs(a_X)",

View File

@ -1767,6 +1767,9 @@ func (ev *evaluator) VectorAnd(lhs, rhs Vector, matching *parser.VectorMatching,
if matching.Card != parser.CardManyToMany {
panic("set operations must only use many-to-many matching")
}
if len(lhs) == 0 || len(rhs) == 0 {
return nil // Short-circuit: AND with nothing is nothing.
}
// The set of signatures for the right-hand side Vector.
rightSigs := map[string]struct{}{}
@ -1788,6 +1791,11 @@ func (ev *evaluator) VectorOr(lhs, rhs Vector, matching *parser.VectorMatching,
if matching.Card != parser.CardManyToMany {
panic("set operations must only use many-to-many matching")
}
if len(lhs) == 0 { // Short-circuit.
return rhs
} else if len(rhs) == 0 {
return lhs
}
leftSigs := map[string]struct{}{}
// Add everything from the left-hand-side Vector.
@ -1808,6 +1816,11 @@ func (ev *evaluator) VectorUnless(lhs, rhs Vector, matching *parser.VectorMatchi
if matching.Card != parser.CardManyToMany {
panic("set operations must only use many-to-many matching")
}
// Short-circuit: empty rhs means we will return everything in lhs;
// empty lhs means we will return empty - don't need to build a map.
if len(lhs) == 0 || len(rhs) == 0 {
return lhs
}
rightSigs := map[string]struct{}{}
for _, sh := range rhsh {
@ -1827,6 +1840,9 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
if matching.Card == parser.CardManyToMany {
panic("many-to-many only allowed for set operators")
}
if len(lhs) == 0 || len(rhs) == 0 {
return nil // Short-circuit: nothing is going to match.
}
// The control flow below handles one-to-one or many-to-one matching.
// For one-to-many, swap sidedness and account for the swap when calculating