Skip to content
This repository was archived by the owner on Aug 23, 2023. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3b6ab0c

Browse files
committedJun 8, 2018
Add method to cache many chunks at once
1 parent e028846 commit 3b6ab0c

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed
 

‎mdata/cache/ccache_metric.go

+60
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,66 @@ func (mc *CCacheMetric) Del(ts uint32) int {
6969
return len(mc.chunks)
7070
}
7171

72+
func (mc *CCacheMetric) AddSlice(prev uint32, itergens []chunk.IterGen) {
73+
if len(itergens) == 0 {
74+
return
75+
}
76+
77+
mc.Lock()
78+
defer mc.Unlock()
79+
80+
ts := itergens[0].Ts
81+
82+
// if previous chunk has not been passed we try to be smart and figure it out.
83+
// this is common in a scenario where a metric continuously gets queried
84+
// for a range that starts less than one chunkspan before now().
85+
if prev == 0 {
86+
res, ok := mc.seekDesc(ts - 1)
87+
if ok {
88+
prev = res
89+
}
90+
}
91+
92+
for _, itergen := range itergens {
93+
ts = itergen.Ts
94+
95+
if _, ok := mc.chunks[ts]; ok {
96+
// chunk is already present. no need to error on that, just ignore it
97+
continue
98+
}
99+
100+
mc.chunks[ts] = &CCacheChunk{
101+
Ts: ts,
102+
Prev: 0,
103+
Next: 0,
104+
Itgen: itergen,
105+
}
106+
107+
// if the previous chunk is cached, link in both directions
108+
if _, ok := mc.chunks[prev]; ok {
109+
mc.chunks[prev].Next = ts
110+
mc.chunks[ts].Prev = prev
111+
}
112+
prev = ts
113+
}
114+
115+
nextTs := mc.nextTs(ts)
116+
117+
// if nextTs() can't figure out the end date it returns ts
118+
if nextTs > ts {
119+
// if the next chunk is cached, link in both directions
120+
if _, ok := mc.chunks[nextTs]; ok {
121+
mc.chunks[nextTs].Prev = ts
122+
mc.chunks[ts].Next = nextTs
123+
}
124+
}
125+
126+
// regenerate the list of sorted keys after adding a chunk
127+
mc.generateKeys()
128+
129+
return
130+
}
131+
72132
func (mc *CCacheMetric) Add(prev uint32, itergen chunk.IterGen) {
73133
ts := itergen.Ts
74134

‎mdata/cache/ccache_metric_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package cache
2+
3+
import (
4+
"testing"
5+
6+
"github.com/grafana/metrictank/mdata/chunk"
7+
"gopkg.in/raintank/schema.v1"
8+
)
9+
10+
func generateChunks(b *testing.B) []chunk.IterGen {
11+
res := make([]chunk.IterGen, 0, b.N)
12+
13+
// the metric is initialized with the first chunk at ts 1,
14+
// so the generated slice should start at ts 2
15+
for i := uint32(2); i < uint32(b.N+2); i++ {
16+
c := getItgen(b, []uint32{1}, i, true)
17+
res = append(res, c)
18+
}
19+
return res
20+
}
21+
22+
func initMetric(b *testing.B) *CCacheMetric {
23+
ccm := NewCCacheMetric()
24+
mkey, _ := schema.MKeyFromString("1.12345678901234567890123456789012")
25+
c := getItgen(b, []uint32{1}, uint32(1), true)
26+
ccm.Init(mkey, 0, c)
27+
return ccm
28+
}
29+
30+
func BenchmarkAddingManyChunksOneByOne(b *testing.B) {
31+
ccm := initMetric(b)
32+
chunks := generateChunks(b)
33+
prev := uint32(1)
34+
b.ResetTimer()
35+
for _, chunk := range chunks {
36+
ccm.Add(prev, chunk)
37+
prev = chunk.Ts
38+
}
39+
}
40+
41+
func BenchmarkAddingManyChunksAtOnce(b *testing.B) {
42+
ccm := initMetric(b)
43+
chunks := generateChunks(b)
44+
prev := uint32(1)
45+
b.ResetTimer()
46+
ccm.AddSlice(prev, chunks)
47+
}

‎mdata/cache/ccache_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
// getItgen returns an IterGen which holds a chunk which has directly encoded all values
14-
func getItgen(t *testing.T, values []uint32, ts uint32, spanaware bool) chunk.IterGen {
14+
func getItgen(t testing.TB, values []uint32, ts uint32, spanaware bool) chunk.IterGen {
1515
var b []byte
1616
buf := new(bytes.Buffer)
1717
if spanaware {

0 commit comments

Comments
 (0)