@@ -12,6 +12,8 @@ import (
12
12
"github.com/grafana/pyroscope/pkg/util"
13
13
)
14
14
15
+ const defaultBlockBatchSize = 20
16
+
15
17
type compactionKey struct {
16
18
// Order of the fields is not important.
17
19
// Can be generalized.
@@ -21,14 +23,14 @@ type compactionKey struct {
21
23
}
22
24
23
25
type compactionQueue struct {
24
- strategy Strategy
26
+ config Config
25
27
registerer prometheus.Registerer
26
28
levels []* blockQueue
27
29
}
28
30
29
31
// blockQueue stages blocks as they are being added. Once a batch of blocks
30
- // within the compaction key reaches a certain size, it is pushed to the linked
31
- // list in the arrival order and to the compaction key queue.
32
+ // within the compaction key reaches a certain size or age , it is pushed to
33
+ // the linked list in the arrival order and to the compaction key queue.
32
34
//
33
35
// This allows to iterate over the blocks in the order of arrival within the
34
36
// compaction dimension, while maintaining an ability to remove blocks from the
@@ -38,7 +40,7 @@ type compactionQueue struct {
38
40
// the queue is through explicit removal. Batch and block iterators provide
39
41
// the read access.
40
42
type blockQueue struct {
41
- strategy Strategy
43
+ config Config
42
44
registerer prometheus.Registerer
43
45
staged map [compactionKey ]* stagedBlocks
44
46
// Batches ordered by arrival.
@@ -97,11 +99,12 @@ type batch struct {
97
99
// Links to the local batch queue items:
98
100
// batches that share the same compaction key.
99
101
next , prev * batch
102
+ createdAt int64
100
103
}
101
104
102
- func newCompactionQueue (strategy Strategy , registerer prometheus.Registerer ) * compactionQueue {
105
+ func newCompactionQueue (config Config , registerer prometheus.Registerer ) * compactionQueue {
103
106
return & compactionQueue {
104
- strategy : strategy ,
107
+ config : config ,
105
108
registerer : registerer ,
106
109
}
107
110
}
@@ -125,11 +128,11 @@ func (q *compactionQueue) push(e compaction.BlockEntry) bool {
125
128
shard : e .Shard ,
126
129
level : e .Level ,
127
130
})
131
+ staged .updatedAt = e .AppendedAt
128
132
pushed := staged .push (blockEntry {
129
133
id : e .ID ,
130
134
index : e .Index ,
131
135
})
132
- staged .updatedAt = e .AppendedAt
133
136
heap .Fix (level .updates , staged .heapIndex )
134
137
level .flushOldest (e .AppendedAt )
135
138
return pushed
@@ -142,15 +145,15 @@ func (q *compactionQueue) blockQueue(l uint32) *blockQueue {
142
145
}
143
146
level := q .levels [l ]
144
147
if level == nil {
145
- level = newBlockQueue (q .strategy , q .registerer )
148
+ level = newBlockQueue (q .config , q .registerer )
146
149
q .levels [l ] = level
147
150
}
148
151
return level
149
152
}
150
153
151
- func newBlockQueue (strategy Strategy , registerer prometheus.Registerer ) * blockQueue {
154
+ func newBlockQueue (config Config , registerer prometheus.Registerer ) * blockQueue {
152
155
return & blockQueue {
153
- strategy : strategy ,
156
+ config : config ,
154
157
registerer : registerer ,
155
158
staged : make (map [compactionKey ]* stagedBlocks ),
156
159
updates : new (priorityBlockQueue ),
@@ -201,14 +204,17 @@ func (s *stagedBlocks) push(block blockEntry) bool {
201
204
}
202
205
s .refs [block .id ] = blockRef {batch : s .batch , index : len (s .batch .blocks )}
203
206
s .batch .blocks = append (s .batch .blocks , block )
207
+ if s .batch .size == 0 {
208
+ s .batch .createdAt = s .updatedAt
209
+ }
204
210
s .batch .size ++
205
211
s .stats .blocks .Add (1 )
206
- if s .queue .strategy . flush (s .batch ) && ! s . flush () {
207
- // An attempt to flush the same batch twice.
208
- // Should not be possible .
209
- return false
212
+ if ! s .queue .config . exceedsMaxSize (s .batch ) &&
213
+ ! s . queue . config . exceedsMaxAge ( s . batch , s . updatedAt ) {
214
+ // The batch is still valid .
215
+ return true
210
216
}
211
- return true
217
+ return s . flush ()
212
218
}
213
219
214
220
func (s * stagedBlocks ) flush () (flushed bool ) {
@@ -221,7 +227,6 @@ func (s *stagedBlocks) flush() (flushed bool) {
221
227
}
222
228
223
229
func (s * stagedBlocks ) resetBatch () {
224
- // TODO(kolesnikovae): get from pool.
225
230
s .batch = & batch {
226
231
blocks : make ([]blockEntry , 0 , defaultBlockBatchSize ),
227
232
staged : s ,
@@ -244,7 +249,6 @@ func (s *stagedBlocks) delete(block string) blockEntry {
244
249
s .stats .blocks .Add (- 1 )
245
250
if ref .batch .size == 0 {
246
251
s .queue .removeBatch (ref .batch )
247
- // TODO(kolesnikovae): return to pool.
248
252
}
249
253
delete (s .refs , block )
250
254
if len (s .refs ) == 0 {
@@ -317,7 +321,7 @@ func (q *blockQueue) flushOldest(now int64) {
317
321
return
318
322
}
319
323
oldest := (* q .updates )[0 ]
320
- if ! q .strategy . flushByAge (oldest .batch , now ) {
324
+ if ! q .config . exceedsMaxAge (oldest .batch , now ) {
321
325
return
322
326
}
323
327
heap .Pop (q .updates )
@@ -369,6 +373,8 @@ func (i *batchIter) next() (*batch, bool) {
369
373
return b , b != nil
370
374
}
371
375
376
+ func (i * batchIter ) reset (b * batch ) { i .batch = b }
377
+
372
378
// batchIter iterates over the batches in the queue, in the order of arrival
373
379
// within the compaction key. It's guaranteed that returned blocks are unique
374
380
// across all batched.
@@ -393,7 +399,14 @@ func (it *blockIter) setBatch(b *batch) {
393
399
it .i = 0
394
400
}
395
401
396
- func (it * blockIter ) next () (string , bool ) {
402
+ func (it * blockIter ) more () bool {
403
+ if it .batch == nil {
404
+ return false
405
+ }
406
+ return it .i < len (it .batch .blocks )
407
+ }
408
+
409
+ func (it * blockIter ) peek () (string , bool ) {
397
410
for it .batch != nil {
398
411
if it .i >= len (it .batch .blocks ) {
399
412
it .setBatch (it .batch .next )
@@ -404,9 +417,13 @@ func (it *blockIter) next() (string, bool) {
404
417
it .i ++
405
418
continue
406
419
}
407
- it .visited [entry .id ] = struct {}{}
408
- it .i ++
409
420
return entry .id , true
410
421
}
411
422
return "" , false
412
423
}
424
+
425
+ func (it * blockIter ) advance () {
426
+ entry := it .batch .blocks [it .i ]
427
+ it .visited [entry .id ] = struct {}{}
428
+ it .i ++
429
+ }
0 commit comments