Skip to content

Commit d5859be

Browse files
committed
shard fingerprints
Signed-off-by: yuanchao <[email protected]>
1 parent 1892ea3 commit d5859be

File tree

1 file changed

+73
-23
lines changed

1 file changed

+73
-23
lines changed

pkg/ingester/index/index.go

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package index
22

33
import (
4+
"math"
45
"sort"
56
"sync"
67
"unsafe"
@@ -88,12 +89,68 @@ func (ii *InvertedIndex) Delete(labels labels.Labels, fp model.Fingerprint) {
8889
// NB slice entries are sorted in fp order.
8990
type indexEntry struct {
9091
name string
91-
fps map[string]indexValueEntry
92+
fps map[string]*indexValueEntry
9293
}
9394

9495
type indexValueEntry struct {
9596
value string
96-
fps []model.Fingerprint
97+
shards [][]model.Fingerprint
98+
}
99+
100+
101+
const indexValueShards = 200
102+
103+
func newIndexValueEntry(value string) *indexValueEntry {
104+
shards := make([][]model.Fingerprint, indexValueShards)
105+
return &indexValueEntry{
106+
value: value,
107+
shards: shards,
108+
}
109+
}
110+
111+
func (c *indexValueEntry) fps() []model.Fingerprint {
112+
var fps []model.Fingerprint
113+
for _, shard := range c.shards {
114+
fps = append(fps, shard...)
115+
}
116+
return fps
117+
}
118+
119+
func (c *indexValueEntry) delete(fp model.Fingerprint){
120+
num := c.shard(fp)
121+
fps := c.shards[num]
122+
j := sort.Search(len(fps), func(i int) bool {
123+
return fps[i] >= fp
124+
})
125+
c.shards[num] = fps[:j+copy(fps[j:], fps[j+1:])]
126+
if len(c.shards[num]) == 0 {
127+
c.shards[num] = []model.Fingerprint{}
128+
}
129+
}
130+
131+
func (c *indexValueEntry) length() int {
132+
var i int
133+
for _, shard := range c.shards {
134+
i += len(shard)
135+
}
136+
return i
137+
}
138+
139+
func (c *indexValueEntry) shard(fp model.Fingerprint) int {
140+
return int(math.Floor(float64(len(c.shards)) * float64(fp) / math.MaxUint64))
141+
}
142+
143+
func (c *indexValueEntry) add(fp model.Fingerprint){
144+
num := c.shard(fp)
145+
fps := c.shards[num]
146+
// Insert into the right position to keep fingerprints sorted
147+
j := sort.Search(len(fps), func(i int) bool {
148+
return fps[i] >= fp
149+
})
150+
fps = append(fps, 0)
151+
copy(fps[j+1:], fps[j:])
152+
fps[j] = fp
153+
c.shards[num] = fps
97154
}
98155

99156
type unlockIndex map[string]indexEntry
@@ -126,23 +183,15 @@ func (shard *indexShard) add(metric []client.LabelAdapter, fp model.Fingerprint)
126183
if !ok {
127184
values = indexEntry{
128185
name: copyString(pair.Name),
129-
fps: map[string]indexValueEntry{},
186+
fps: map[string]*indexValueEntry{},
130187
}
131188
shard.idx[values.name] = values
132189
}
133190
fingerprints, ok := values.fps[pair.Value]
134191
if !ok {
135-
fingerprints = indexValueEntry{
136-
value: copyString(pair.Value),
137-
}
192+
fingerprints = newIndexValueEntry(copyString(pair.Value))
138193
}
139-
// Insert into the right position to keep fingerprints sorted
140-
j := sort.Search(len(fingerprints.fps), func(i int) bool {
141-
return fingerprints.fps[i] >= fp
142-
})
143-
fingerprints.fps = append(fingerprints.fps, 0)
144-
copy(fingerprints.fps[j+1:], fingerprints.fps[j:])
145-
fingerprints.fps[j] = fp
194+
fingerprints.add(fp)
146195
values.fps[fingerprints.value] = fingerprints
147196
internedLabels[i] = labels.Label{Name: values.name, Value: fingerprints.value}
148197
}
@@ -167,21 +216,26 @@ func (shard *indexShard) lookup(matchers []*labels.Matcher) []model.Fingerprint
167216
}
168217
var toIntersect model.Fingerprints
169218
if matcher.Type == labels.MatchEqual {
170-
fps := values.fps[matcher.Value]
171-
toIntersect = append(toIntersect, fps.fps...) // deliberate copy
219+
fps, ok := values.fps[matcher.Value]
220+
if ok {
221+
toIntersect = append(toIntersect, fps.fps()...) // deliberate copy
222+
}
172223
} else if matcher.Type == labels.MatchRegexp && len(chunk.FindSetMatches(matcher.Value)) > 0 {
173224
// The lookup is of the form `=~"a|b|c|d"`
174225
set := chunk.FindSetMatches(matcher.Value)
175226
for _, value := range set {
176-
toIntersect = append(toIntersect, values.fps[value].fps...)
227+
fps, ok := values.fps[value]
228+
if ok {
229+
toIntersect = append(toIntersect, fps.fps()...)
230+
}
177231
}
178232
sort.Sort(toIntersect)
179233
} else {
180234
// accumulate the matching fingerprints (which are all distinct)
181235
// then sort to maintain the invariant
182236
for value, fps := range values.fps {
183237
if matcher.Matches(value) {
184-
toIntersect = append(toIntersect, fps.fps...)
238+
toIntersect = append(toIntersect, fps.fps()...)
185239
}
186240
}
187241
sort.Sort(toIntersect)
@@ -240,13 +294,9 @@ func (shard *indexShard) delete(labels labels.Labels, fp model.Fingerprint) {
240294
if !ok {
241295
continue
242296
}
297+
fingerprints.delete(fp)
243298

244-
j := sort.Search(len(fingerprints.fps), func(i int) bool {
245-
return fingerprints.fps[i] >= fp
246-
})
247-
fingerprints.fps = fingerprints.fps[:j+copy(fingerprints.fps[j:], fingerprints.fps[j+1:])]
248-
249-
if len(fingerprints.fps) == 0 {
299+
if fingerprints.length() == 0 {
250300
delete(values.fps, value)
251301
} else {
252302
values.fps[value] = fingerprints

0 commit comments

Comments
 (0)