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:
parent
c4942ef3b7
commit
5a754bc043
|
@ -130,6 +130,9 @@ func BenchmarkRangeQuery(b *testing.B) {
|
||||||
{
|
{
|
||||||
expr: "a_X unless b_X{l=~'.*[0-4]$'}",
|
expr: "a_X unless b_X{l=~'.*[0-4]$'}",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
expr: "a_X and b_X{l='notfound'}",
|
||||||
|
},
|
||||||
// Simple functions.
|
// Simple functions.
|
||||||
{
|
{
|
||||||
expr: "abs(a_X)",
|
expr: "abs(a_X)",
|
||||||
|
|
|
@ -1767,6 +1767,9 @@ func (ev *evaluator) VectorAnd(lhs, rhs Vector, matching *parser.VectorMatching,
|
||||||
if matching.Card != parser.CardManyToMany {
|
if matching.Card != parser.CardManyToMany {
|
||||||
panic("set operations must only use many-to-many matching")
|
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.
|
// The set of signatures for the right-hand side Vector.
|
||||||
rightSigs := map[string]struct{}{}
|
rightSigs := map[string]struct{}{}
|
||||||
|
@ -1788,6 +1791,11 @@ func (ev *evaluator) VectorOr(lhs, rhs Vector, matching *parser.VectorMatching,
|
||||||
if matching.Card != parser.CardManyToMany {
|
if matching.Card != parser.CardManyToMany {
|
||||||
panic("set operations must only use many-to-many matching")
|
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{}{}
|
leftSigs := map[string]struct{}{}
|
||||||
// Add everything from the left-hand-side Vector.
|
// 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 {
|
if matching.Card != parser.CardManyToMany {
|
||||||
panic("set operations must only use many-to-many matching")
|
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{}{}
|
rightSigs := map[string]struct{}{}
|
||||||
for _, sh := range rhsh {
|
for _, sh := range rhsh {
|
||||||
|
@ -1827,6 +1840,9 @@ func (ev *evaluator) VectorBinop(op parser.ItemType, lhs, rhs Vector, matching *
|
||||||
if matching.Card == parser.CardManyToMany {
|
if matching.Card == parser.CardManyToMany {
|
||||||
panic("many-to-many only allowed for set operators")
|
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.
|
// 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
|
// For one-to-many, swap sidedness and account for the swap when calculating
|
||||||
|
|
Loading…
Reference in New Issue