@@ -81,9 +81,16 @@ func newIdFilter(expressions tagquery.Expressions, ctx *TagQueryContext) *idFilt
81
81
continue
82
82
}
83
83
84
+ // if we don't use an inverted set of meta records, then we want to check if
85
+ // all meta records involved in a meta tag filter use the "=" operator.
86
+ // if this is the case then it is cheaper to build a set of acceptable tags
87
+ // based on the meta record expressions and just check whether they are present
88
+ // in a metric that gets filtered, compared to doing a full tag index lookup
89
+ // to check whether a metric has one of the necessary meta tags associated
90
+ // with it.
91
+ optimizeForOnlyEqualOperators := ! invertSetOfMetaRecords
84
92
var metaRecordFilters []tagquery.MetricDefinitionFilter
85
- onlyEqualOperators := ! invertSetOfMetaRecords
86
- singleEqualExprPerRecord := true
93
+ singleExprPerRecord := true
87
94
records := make ([]tagquery.MetaTagRecord , len (metaRecordIds ))
88
95
for i , id := range metaRecordIds {
89
96
record , ok := ctx .metaTagRecords .records [id ]
@@ -93,24 +100,31 @@ func newIdFilter(expressions tagquery.Expressions, ctx *TagQueryContext) *idFilt
93
100
continue
94
101
}
95
102
96
- if onlyEqualOperators {
103
+ if optimizeForOnlyEqualOperators {
97
104
for exprIdx := range record .Expressions {
98
105
if record .Expressions [exprIdx ].GetOperator () != tagquery .EQUAL {
99
- onlyEqualOperators = false
106
+ optimizeForOnlyEqualOperators = false
100
107
break
101
108
}
102
109
}
103
- records [i ] = record
104
- if len (record .Expressions ) > 1 {
105
- singleEqualExprPerRecord = false
110
+ if optimizeForOnlyEqualOperators {
111
+ records [i ] = record
112
+ if len (record .Expressions ) > 1 {
113
+ singleExprPerRecord = false
114
+ }
106
115
}
107
116
}
108
117
109
118
metaRecordFilters = append (metaRecordFilters , record .GetMetricDefinitionFilter (ctx .index .idHasTag ))
110
119
}
111
120
112
- if onlyEqualOperators {
113
- if singleEqualExprPerRecord {
121
+ if optimizeForOnlyEqualOperators {
122
+ // there are two different ways how we optimize for the case where all expressions
123
+ // of all involved meta records are using the "=" operator. the first and fastest
124
+ // way can only be used if each involved meta record only has one single expression,
125
+ // otherwise we use the second way which is a bit more expensive but it also works
126
+ // if some of the involved meta records have multiple expressions.
127
+ if singleExprPerRecord {
114
128
res .filters [i ].testByMetaTags = metaRecordFilterBySetOfValidValues (records )
115
129
} else {
116
130
res .filters [i ].testByMetaTags = metaRecordFilterBySetOfValidValueSets (records )
@@ -127,7 +141,16 @@ func newIdFilter(expressions tagquery.Expressions, ctx *TagQueryContext) *idFilt
127
141
return & res
128
142
}
129
143
144
+ // metaRecordFilterBySetOfValidValues creates a filter function to filter by a meta tag
145
+ // which only involves meta records of which each only has exactly one expression and that
146
+ // expression is using the "=" operator. this is quite a narrow scenario, but since it is
147
+ // a very common use case it makes sense to optimize for it.
130
148
func metaRecordFilterBySetOfValidValues (records []tagquery.MetaTagRecord ) tagquery.MetricDefinitionFilter {
149
+ // we first build a set of valid tags and names.
150
+ // since we know that each of the involved meta records uses exactly one expression
151
+ // which is using the "=" operator we know that if a given metric's name matches a
152
+ // value in validNames or if one of its tags matches a value in validValues then this
153
+ // is sufficient to let it pass the filter.
131
154
validValues := make (map [string ]struct {})
132
155
validNames := make (map [string ]struct {})
133
156
var builder strings.Builder
@@ -154,12 +177,17 @@ func metaRecordFilterBySetOfValidValues(records []tagquery.MetaTagRecord) tagque
154
177
}
155
178
}
156
179
180
+ // metaRecordFilterBySetOfValidValueSets creates a filter function to filter by a meta tag
181
+ // which only involves meta records of which all expressions are only using the "=" operator,
182
+ // it is ok if one meta record uses multiple such expressions.
157
183
func metaRecordFilterBySetOfValidValueSets (records []tagquery.MetaTagRecord ) tagquery.MetricDefinitionFilter {
184
+ // we first build a set of tag and name value combinations of which each is sufficient
185
+ // to pass the generated filter when a metric contains all values of one of these
186
+ // combinations
158
187
validValueSets := make ([]struct {
159
188
name string
160
189
tags []string
161
190
}, len (records ))
162
-
163
191
var builder strings.Builder
164
192
for i := range records {
165
193
validValueSets [i ].tags = make ([]string , 0 , len (records [i ].Expressions ))
@@ -172,10 +200,13 @@ func metaRecordFilterBySetOfValidValueSets(records []tagquery.MetaTagRecord) tag
172
200
builder .Reset ()
173
201
}
174
202
}
203
+
204
+ // the tags must be sorted because that's a requirement for sliceContainsElements()
175
205
sort .Strings (validValueSets [i ].tags )
176
206
}
177
207
178
208
return func (_ schema.MKey , name string , tags []string ) tagquery.FilterDecision {
209
+ // iterate over the acceptable value combinations and check if one matches this metric
179
210
for _ , validValueSet := range validValueSets {
180
211
if len (validValueSet .name ) > 0 {
181
212
if name != validValueSet .name {
0 commit comments