Skip to content
This repository was archived by the owner on Aug 23, 2023. It is now read-only.

Commit bc6c8b7

Browse files
committed
performance tuning
this changes the sortByCost logic so it puts more weight on the expression type, and only takes cardinality into account when it has to sort two expressions of the same operator cost. in the benchmarks this seems to lead to better results.
1 parent 9d516c8 commit bc6c8b7

13 files changed

+35
-22
lines changed

expr/tagquery/expression.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,10 @@ type Expression interface {
115115
// GetOperator returns the operator of this expression
116116
GetOperator() ExpressionOperator
117117

118-
GetCostMultiplier() uint32
118+
// GetOperatorCost returns a value which should roughly reflect the cost of this operator compared
119+
// to other operators. F.e. = is cheaper than =~. Keep in mind that this is only a very rough
120+
// estimate and will never be accurate.
121+
GetOperatorCost() uint32
119122

120123
// OperatesOnTag returns whether this expression operators on the tag key
121124
// (if not, it operates on the value).

expr/tagquery/expression_equal.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (e *expressionEqual) GetOperator() ExpressionOperator {
2222
return EQUAL
2323
}
2424

25-
func (e *expressionEqual) GetCostMultiplier() uint32 {
25+
func (e *expressionEqual) GetOperatorCost() uint32 {
2626
return 1
2727
}
2828

expr/tagquery/expression_has_tag.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ func (e *expressionHasTag) GetOperator() ExpressionOperator {
2222
return HAS_TAG
2323
}
2424

25-
func (e *expressionHasTag) GetCostMultiplier() uint32 {
26-
return 2
25+
func (e *expressionHasTag) GetOperatorCost() uint32 {
26+
return 10
2727
}
2828

2929
func (e *expressionHasTag) OperatesOnTag() bool {

expr/tagquery/expression_match.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ func (e *expressionMatch) GetOperator() ExpressionOperator {
3333
return MATCH
3434
}
3535

36-
func (e *expressionMatch) GetCostMultiplier() uint32 {
37-
return 0
36+
func (e *expressionMatch) GetOperatorCost() uint32 {
37+
return 10
3838
}
3939

4040
func (e *expressionMatch) RequiresNonEmptyValue() bool {

expr/tagquery/expression_match_all.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (e *expressionMatchAll) GetOperator() ExpressionOperator {
3232
return MATCH_ALL
3333
}
3434

35-
func (e *expressionMatchAll) GetCostMultiplier() uint32 {
35+
func (e *expressionMatchAll) GetOperatorCost() uint32 {
3636
return 50
3737
}
3838

expr/tagquery/expression_match_none.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (e *expressionMatchNone) GetOperator() ExpressionOperator {
3232
return MATCH_NONE
3333
}
3434

35-
func (e *expressionMatchNone) GetCostMultiplier() uint32 {
35+
func (e *expressionMatchNone) GetOperatorCost() uint32 {
3636
return 0
3737
}
3838

expr/tagquery/expression_match_tag.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (e *expressionMatchTag) GetOperator() ExpressionOperator {
2424
return MATCH_TAG
2525
}
2626

27-
func (e *expressionMatchTag) GetCostMultiplier() uint32 {
27+
func (e *expressionMatchTag) GetOperatorCost() uint32 {
2828
return 20
2929
}
3030

expr/tagquery/expression_not_equal.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (e *expressionNotEqual) GetOperator() ExpressionOperator {
2222
return NOT_EQUAL
2323
}
2424

25-
func (e *expressionNotEqual) GetCostMultiplier() uint32 {
25+
func (e *expressionNotEqual) GetOperatorCost() uint32 {
2626
return 1
2727
}
2828

expr/tagquery/expression_not_has_tag.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ func (e *expressionNotHasTag) GetOperator() ExpressionOperator {
2222
return NOT_HAS_TAG
2323
}
2424

25-
func (e *expressionNotHasTag) GetCostMultiplier() uint32 {
26-
return 2
25+
func (e *expressionNotHasTag) GetOperatorCost() uint32 {
26+
return 10
2727
}
2828

2929
func (e *expressionNotHasTag) OperatesOnTag() bool {

expr/tagquery/expression_not_match.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (e *expressionNotMatch) GetOperator() ExpressionOperator {
3333
return NOT_MATCH
3434
}
3535

36-
func (e *expressionNotMatch) GetCostMultiplier() uint32 {
36+
func (e *expressionNotMatch) GetOperatorCost() uint32 {
3737
return 10
3838
}
3939

expr/tagquery/expression_prefix.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (e *expressionPrefix) GetOperator() ExpressionOperator {
2222
return PREFIX
2323
}
2424

25-
func (e *expressionPrefix) GetCostMultiplier() uint32 {
25+
func (e *expressionPrefix) GetOperatorCost() uint32 {
2626
return 2
2727
}
2828

expr/tagquery/expression_prefix_tag.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ func (e *expressionPrefixTag) GetOperator() ExpressionOperator {
2222
return PREFIX_TAG
2323
}
2424

25-
func (e *expressionPrefixTag) GetCostMultiplier() uint32 {
26-
return 3
25+
func (e *expressionPrefixTag) GetOperatorCost() uint32 {
26+
return 15
2727
}
2828

2929
func (e *expressionPrefixTag) OperatesOnTag() bool {

idx/memory/tag_query.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ func NewTagQueryContext(query tagquery.Query) TagQueryContext {
4343

4444
func (q *TagQueryContext) prepareExpressions(idx TagIndex) {
4545
type expressionCost struct {
46-
cost uint32
46+
operatorCost uint32
47+
cardinality uint32
4748
expressionIdx int
4849
}
4950
costs := make([]expressionCost, len(q.query.Expressions))
@@ -53,20 +54,29 @@ func (q *TagQueryContext) prepareExpressions(idx TagIndex) {
5354

5455
if expr.OperatesOnTag() {
5556
if expr.MatchesExactly() {
56-
costs[i].cost = uint32(len(idx[expr.GetKey()])) * expr.GetCostMultiplier()
57+
costs[i].operatorCost = expr.GetOperatorCost()
58+
costs[i].cardinality = uint32(len(idx[expr.GetKey()]))
5759
} else {
58-
costs[i].cost = uint32(len(idx)) * expr.GetCostMultiplier()
60+
costs[i].operatorCost = expr.GetOperatorCost()
61+
costs[i].cardinality = uint32(len(idx))
5962
}
6063
} else {
6164
if expr.MatchesExactly() {
62-
costs[i].cost = uint32(len(idx[expr.GetKey()][expr.GetValue()])) * expr.GetCostMultiplier()
65+
costs[i].operatorCost = expr.GetOperatorCost()
66+
costs[i].cardinality = uint32(len(idx[expr.GetKey()][expr.GetValue()]))
6367
} else {
64-
costs[i].cost = uint32(len(idx[expr.GetKey()])) * expr.GetCostMultiplier()
68+
costs[i].operatorCost = expr.GetOperatorCost()
69+
costs[i].cardinality = uint32(len(idx[expr.GetKey()]))
6570
}
6671
}
6772
}
6873

69-
sort.Slice(costs, func(i, j int) bool { return costs[i].cost < costs[j].cost })
74+
sort.Slice(costs, func(i, j int) bool {
75+
if costs[i].operatorCost == costs[j].operatorCost {
76+
return costs[i].cardinality < costs[j].cardinality
77+
}
78+
return costs[i].operatorCost < costs[j].operatorCost
79+
})
7080

7181
// the number of filters / default decisions is equal to the number of expressions - 1
7282
// because one of the expressions will be chosen to be the one that we start with.

0 commit comments

Comments
 (0)