Skip to content

Commit 5f39048

Browse files
codesomegouthamve
authored andcommitted
Refactor enocding.Chunk.Add (#1706)
* Refactor enocding.Chunk.Add Signed-off-by: Ganesh Vernekar <[email protected]> * Undo pointer-to-slice changes in varbit Signed-off-by: Bryan Boreham <[email protected]> * Error on setting Delta encoding Signed-off-by: Ganesh Vernekar <[email protected]> * Don't replace Delta with DoubleDelta Signed-off-by: Ganesh Vernekar <[email protected]>
1 parent da442a0 commit 5f39048

21 files changed

+283
-635
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## master / unreleased
22

3+
* [CHANGE] Removed `Delta` encoding. Any old chunks with `Delta` encoding cannot be read anymore. If `ingester.chunk-encoding` is set to `Delta` the ingester will fail to start. #1706
4+
* [ENHANCEMENT] Allocation improvements in adding samples to Chunk. #1706
5+
36
## 0.3.0 / 2019-10-11
47

58
This release adds support for Redis as an alternative to Memcached, and also includes many optimisations which reduce CPU and memory usage.

pkg/chunk/cache/cache_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,26 @@ func fillCache(t *testing.T, cache cache.Cache) ([]string, []chunk.Chunk) {
2727
chunks := []chunk.Chunk{}
2828
for i := 0; i < 100; i++ {
2929
ts := model.TimeFromUnix(int64(i * chunkLen))
30-
promChunk, _ := prom_chunk.New().Add(model.SamplePair{
30+
promChunk := prom_chunk.New()
31+
nc, err := promChunk.Add(model.SamplePair{
3132
Timestamp: ts,
3233
Value: model.SampleValue(i),
3334
})
35+
require.NoError(t, err)
36+
require.Nil(t, nc)
3437
c := chunk.NewChunk(
3538
userID,
3639
model.Fingerprint(1),
3740
labels.Labels{
3841
{Name: model.MetricNameLabel, Value: "foo"},
3942
{Name: "bar", Value: "baz"},
4043
},
41-
promChunk[0],
44+
promChunk,
4245
ts,
4346
ts.Add(chunkLen),
4447
)
4548

46-
err := c.Encode()
49+
err = c.Encode()
4750
require.NoError(t, err)
4851
buf, err := c.Encoded()
4952
require.NoError(t, err)

pkg/chunk/chunk_store_test.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -579,22 +579,25 @@ func TestChunkStoreRandom(t *testing.T) {
579579
const chunkLen = 2 * 3600 // in seconds
580580
for i := 0; i < 100; i++ {
581581
ts := model.TimeFromUnix(int64(i * chunkLen))
582-
chunks, _ := encoding.New().Add(model.SamplePair{
582+
ch := encoding.New()
583+
nc, err := ch.Add(model.SamplePair{
583584
Timestamp: ts,
584585
Value: model.SampleValue(float64(i)),
585586
})
587+
require.NoError(t, err)
588+
require.Nil(t, nc)
586589
chunk := NewChunk(
587590
userID,
588591
model.Fingerprint(1),
589592
labels.Labels{
590593
{Name: labels.MetricName, Value: "foo"},
591594
{Name: "bar", Value: "baz"},
592595
},
593-
chunks[0],
596+
ch,
594597
ts,
595598
ts.Add(chunkLen*time.Second).Add(-1*time.Second),
596599
)
597-
err := chunk.Encode()
600+
err = chunk.Encode()
598601
require.NoError(t, err)
599602
err = store.Put(ctx, []Chunk{chunk})
600603
require.NoError(t, err)
@@ -644,23 +647,26 @@ func TestChunkStoreLeastRead(t *testing.T) {
644647
const chunkLen = 60 // in seconds
645648
for i := 0; i < 24; i++ {
646649
ts := model.TimeFromUnix(int64(i * chunkLen))
647-
chunks, _ := encoding.New().Add(model.SamplePair{
650+
ch := encoding.New()
651+
nc, err := ch.Add(model.SamplePair{
648652
Timestamp: ts,
649653
Value: model.SampleValue(float64(i)),
650654
})
655+
require.NoError(t, err)
656+
require.Nil(t, nc)
651657
chunk := NewChunk(
652658
userID,
653659
model.Fingerprint(1),
654660
labels.Labels{
655661
{Name: labels.MetricName, Value: "foo"},
656662
{Name: "bar", Value: "baz"},
657663
},
658-
chunks[0],
664+
ch,
659665
ts,
660666
ts.Add(chunkLen*time.Second),
661667
)
662668
t.Logf("Loop %d", i)
663-
err := chunk.Encode()
669+
err = chunk.Encode()
664670
require.NoError(t, err)
665671
err = store.Put(ctx, []Chunk{chunk})
666672
require.NoError(t, err)

pkg/chunk/chunk_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ func dummyChunkForEncoding(now model.Time, metric labels.Labels, enc encoding.En
3636
c, _ := encoding.NewForEncoding(enc)
3737
for i := 0; i < samples; i++ {
3838
t := time.Duration(i) * 15 * time.Second
39-
cs, err := c.Add(model.SamplePair{Timestamp: now.Add(t), Value: 0})
39+
nc, err := c.Add(model.SamplePair{Timestamp: now.Add(t), Value: 0})
4040
if err != nil {
4141
panic(err)
4242
}
43-
c = cs[0]
43+
if nc != nil {
44+
panic("returned chunk was not nil")
45+
}
4446
}
4547
chunk := NewChunk(
4648
userID,

pkg/chunk/encoding/bigchunk.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ func newBigchunk() *bigchunk {
3232
return &bigchunk{}
3333
}
3434

35-
func (b *bigchunk) Add(sample model.SamplePair) ([]Chunk, error) {
35+
func (b *bigchunk) Add(sample model.SamplePair) (Chunk, error) {
3636
if b.remainingSamples == 0 {
3737
if bigchunkSizeCapBytes > 0 && b.Size() > bigchunkSizeCapBytes {
38-
return addToOverflowChunk(b, sample)
38+
return addToOverflowChunk(sample)
3939
}
4040
if err := b.addNextChunk(sample.Timestamp); err != nil {
4141
return nil, err
@@ -44,7 +44,7 @@ func (b *bigchunk) Add(sample model.SamplePair) ([]Chunk, error) {
4444

4545
b.appender.Append(int64(sample.Timestamp), float64(sample.Value))
4646
b.remainingSamples--
47-
return []Chunk{b}, nil
47+
return nil, nil
4848
}
4949

5050
// addNextChunk adds a new XOR "subchunk" to the internal list of chunks.

pkg/chunk/encoding/bigchunk_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import (
1212
func TestSliceBiggerChunk(t *testing.T) {
1313
var c Chunk = newBigchunk()
1414
for i := 0; i < 12*3600/15; i++ {
15-
cs, err := c.Add(model.SamplePair{
15+
nc, err := c.Add(model.SamplePair{
1616
Timestamp: model.Time(i * step),
1717
Value: model.SampleValue(i),
1818
})
1919
require.NoError(t, err)
20-
c = cs[0]
20+
require.Nil(t, nc)
2121
}
2222

2323
// Test for when the slice aligns perfectly with the sub-chunk boundaries.
@@ -69,12 +69,12 @@ func BenchmarkBiggerChunkMemory(b *testing.B) {
6969
for i := 0; i < b.N; i++ {
7070
var c Chunk = newBigchunk()
7171
for i := 0; i < 12*3600/15; i++ {
72-
cs, err := c.Add(model.SamplePair{
72+
nc, err := c.Add(model.SamplePair{
7373
Timestamp: model.Time(i * step),
7474
Value: model.SampleValue(i),
7575
})
7676
require.NoError(b, err)
77-
c = cs[0]
77+
require.Nil(b, nc)
7878
}
7979

8080
c.(*bigchunk).printSize()

pkg/chunk/encoding/chunk.go

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,10 @@ var (
3838
// goroutine-safe.
3939
type Chunk interface {
4040
// Add adds a SamplePair to the chunks, performs any necessary
41-
// re-encoding, and adds any necessary overflow chunks. It returns the
42-
// new version of the original chunk, followed by overflow chunks, if
43-
// any. The first chunk returned might be the same as the original one
44-
// or a newly allocated version. In any case, take the returned chunk as
45-
// the relevant one and discard the original chunk.
46-
Add(sample model.SamplePair) ([]Chunk, error)
41+
// re-encoding, and creates any necessary overflow chunk.
42+
// The returned Chunk is the overflow chunk if it was created.
43+
// The returned Chunk is nil if the sample got appended to the same chunk.
44+
Add(sample model.SamplePair) (Chunk, error)
4745
// NewIterator returns an iterator for the chunks.
4846
// The iterator passed as argument is for re-use. Depending on implementation,
4947
// the iterator can be re-used or a new iterator can be allocated.
@@ -123,12 +121,13 @@ func RangeValues(it Iterator, in metric.Interval) ([]model.SamplePair, error) {
123121
// addToOverflowChunk is a utility function that creates a new chunk as overflow
124122
// chunk, adds the provided sample to it, and returns a chunk slice containing
125123
// the provided old chunk followed by the new overflow chunk.
126-
func addToOverflowChunk(c Chunk, s model.SamplePair) ([]Chunk, error) {
127-
overflowChunks, err := New().Add(s)
124+
func addToOverflowChunk(s model.SamplePair) (Chunk, error) {
125+
overflowChunk := New()
126+
_, err := overflowChunk.Add(s)
128127
if err != nil {
129128
return nil, err
130129
}
131-
return []Chunk{c, overflowChunks[0]}, nil
130+
return overflowChunk, nil
132131
}
133132

134133
// transcodeAndAdd is a utility function that transcodes the dst chunk into the
@@ -139,27 +138,33 @@ func transcodeAndAdd(dst Chunk, src Chunk, s model.SamplePair) ([]Chunk, error)
139138
Ops.WithLabelValues(Transcode).Inc()
140139

141140
var (
142-
head = dst
143-
body, NewChunks []Chunk
144-
err error
141+
head = dst
142+
newChunk Chunk
143+
body = []Chunk{head}
144+
err error
145145
)
146146

147147
it := src.NewIterator(nil)
148148
for it.Scan() {
149-
if NewChunks, err = head.Add(it.Value()); err != nil {
149+
if newChunk, err = head.Add(it.Value()); err != nil {
150150
return nil, err
151151
}
152-
body = append(body, NewChunks[:len(NewChunks)-1]...)
153-
head = NewChunks[len(NewChunks)-1]
152+
if newChunk != nil {
153+
body = append(body, newChunk)
154+
head = newChunk
155+
}
154156
}
155157
if it.Err() != nil {
156158
return nil, it.Err()
157159
}
158160

159-
if NewChunks, err = head.Add(s); err != nil {
161+
if newChunk, err = head.Add(s); err != nil {
160162
return nil, err
161163
}
162-
return append(body, NewChunks...), nil
164+
if newChunk != nil {
165+
body = append(body, newChunk)
166+
}
167+
return body, nil
163168
}
164169

165170
// indexAccessor allows accesses to samples by index.

pkg/chunk/encoding/chunk_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929

3030
func TestLen(t *testing.T) {
3131
chunks := []Chunk{}
32-
for _, encoding := range []Encoding{Delta, DoubleDelta, Varbit} {
32+
for _, encoding := range []Encoding{DoubleDelta, Varbit, Bigchunk} {
3333
c, err := NewForEncoding(encoding)
3434
if err != nil {
3535
t.Fatal(err)
@@ -43,11 +43,12 @@ func TestLen(t *testing.T) {
4343
t.Errorf("chunk type %s should have %d samples, had %d", c.Encoding(), i, c.Len())
4444
}
4545

46-
cs, _ := c.Add(model.SamplePair{
46+
cs, err := c.Add(model.SamplePair{
4747
Timestamp: model.Time(i),
4848
Value: model.SampleValue(i),
4949
})
50-
c = cs[0]
50+
require.NoError(t, err)
51+
require.Nil(t, cs)
5152
}
5253
}
5354
}
@@ -95,13 +96,12 @@ func mkChunk(t *testing.T, encoding Encoding, samples int) Chunk {
9596
require.NoError(t, err)
9697

9798
for i := 0; i < samples; i++ {
98-
chunks, err := chunk.Add(model.SamplePair{
99+
newChunk, err := chunk.Add(model.SamplePair{
99100
Timestamp: model.Time(i * step),
100101
Value: model.SampleValue(i),
101102
})
102103
require.NoError(t, err)
103-
require.Len(t, chunks, 1)
104-
chunk = chunks[0]
104+
require.Nil(t, newChunk)
105105
}
106106

107107
return chunk

0 commit comments

Comments
 (0)