Skip to content

Commit c2a18bc

Browse files
authored
Use a map instead of string to dedupe/track allowed matchers (#13052)
Every time `matcher.String()` is called on a matcher, 1024 bytes are reserved to build the string. We don't _need_ to do this, since comparison by string is just a shorthand for comparison by name, type, and value. Relates to #11920
1 parent 664d2c7 commit c2a18bc

File tree

1 file changed

+39
-13
lines changed

1 file changed

+39
-13
lines changed

pkg/ingester/lookupplan/matcher_reducer_planner.go

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,23 @@ func buildOutMatchers(inMatchers []*labels.Matcher, allowedOutMatchers []*labels
6666
outMatchers := make([]*labels.Matcher, 0, len(inMatchers))
6767
dedupedMatchers, dropped := dedupeMatchers(inMatchers)
6868

69-
// allowedInResultSet's keys are strings of matchers which are returned from setReduceMatchers(),
70-
// and its values track whether each matcher string is already represented in outMatchers.
71-
allowedInResultSet := make(map[string]bool, len(allowedOutMatchers))
69+
// allowedInResultSet maps the relevant values of matchers returned by setReduce.
70+
// The innermost map value tracks whether that matcher is already represented in outMatchers.
71+
// We do it this way instead of using the matcher string via m.String()
72+
// to avoid unnecessary memory allocations when building the string.
73+
allowedInResultSet := make(map[labels.MatchType]map[string]map[string]bool, 4)
7274
for _, m := range allowedOutMatchers {
73-
allowedInResultSet[m.String()] = false
75+
if _, ok := allowedInResultSet[m.Type][m.Name]; ok {
76+
allowedInResultSet[m.Type][m.Name][m.Value] = false
77+
continue
78+
}
79+
val := map[string]bool{m.Value: false}
80+
if _, ok := allowedInResultSet[m.Type]; ok {
81+
allowedInResultSet[m.Type][m.Name] = val
82+
continue
83+
}
84+
name := map[string]map[string]bool{m.Name: val}
85+
allowedInResultSet[m.Type] = name
7486
}
7587
// If we have reached the last deduped input matcher and are still not returning any matchers,
7688
// we should return at least one matcher. This can happen if all input matchers are wildcard matchers.
@@ -82,9 +94,9 @@ func buildOutMatchers(inMatchers []*labels.Matcher, allowedOutMatchers []*labels
8294
// allowedOutMatchers is used to both keep track of all unique matchers (evidenced by existence in the map),
8395
// and whether the matcher has already been seen and added to a set of output matchers (evidenced by the value in the map).
8496
// We only want to add the matcher if it hasn't already been added to an output slice.
85-
if alreadyInResultSet, allowed := allowedInResultSet[m.String()]; allowed && !alreadyInResultSet {
97+
if alreadyInResultSet, allowed := allowedInResultSet[m.Type][m.Name][m.Value]; allowed && !alreadyInResultSet {
8698
outMatchers = append(outMatchers, m)
87-
allowedInResultSet[m.String()] = true
99+
allowedInResultSet[m.Type][m.Name][m.Value] = true
88100
} else {
89101
dropped = append(dropped, m)
90102
}
@@ -125,20 +137,34 @@ func setReduceMatchers(ms []*labels.Matcher) []*labels.Matcher {
125137
return outMatchers
126138
}
127139

128-
// dedupeMatchers dedupes matchers based on their matcher string.
140+
// dedupeMatchers dedupes matchers based on their type, name, and value.
129141
func dedupeMatchers(ms []*labels.Matcher) ([]*labels.Matcher, []*labels.Matcher) {
130-
deduped := make(map[string]*labels.Matcher, len(ms))
142+
deduped := make(map[labels.MatchType]map[string]map[string]*labels.Matcher, 4)
131143
dropped := make([]*labels.Matcher, 0, 1)
132144
for _, m := range ms {
133-
if _, ok := deduped[m.String()]; !ok {
134-
deduped[m.String()] = m
135-
} else {
145+
if _, ok := deduped[m.Type][m.Name][m.Value]; ok {
136146
dropped = append(dropped, m)
147+
continue
137148
}
149+
if _, ok := deduped[m.Type][m.Name]; ok {
150+
deduped[m.Type][m.Name][m.Value] = m
151+
continue
152+
}
153+
valPtr := map[string]*labels.Matcher{m.Value: m}
154+
if _, ok := deduped[m.Type]; ok {
155+
deduped[m.Type][m.Name] = valPtr
156+
continue
157+
}
158+
name := map[string]map[string]*labels.Matcher{m.Name: valPtr}
159+
deduped[m.Type] = name
138160
}
139161
outMatchers := make([]*labels.Matcher, 0, len(deduped))
140-
for _, ptr := range deduped {
141-
outMatchers = append(outMatchers, ptr)
162+
for _, nameMap := range deduped {
163+
for _, valMap := range nameMap {
164+
for _, ptr := range valMap {
165+
outMatchers = append(outMatchers, ptr)
166+
}
167+
}
142168
}
143169
return outMatchers, dropped
144170
}

0 commit comments

Comments
 (0)