Skip to content

Instantly share code, notes, and snippets.

@robert-milan
Last active October 3, 2018 01:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robert-milan/20d87f10456b23f297c9eb9e7d730190 to your computer and use it in GitHub Desktop.
Save robert-milan/20d87f10456b23f297c9eb9e7d730190 to your computer and use it in GitHub Desktop.
Evict Memory Leak Testing (before and after fix) (master / cebc212)
package cache
import (
"bytes"
"encoding/binary"
"fmt"
"runtime"
"sync"
"testing"
"time"
"github.com/grafana/metrictank/mdata/chunk"
"github.com/grafana/metrictank/test"
"github.com/raintank/schema"
)
// getItgen returns an IterGen which holds a chunk which has directly encoded all values
// it assumes the data has step=1, deriving the span as len(values)
func getItgen(t testing.TB, values []uint32, ts uint32, spanaware bool) chunk.IterGen {
var b []byte
buf := new(bytes.Buffer)
if spanaware {
binary.Write(buf, binary.LittleEndian, uint8(chunk.FormatStandardGoTszWithSpan))
span := uint32(len(values))
spanCode, ok := chunk.RevChunkSpans[span]
if !ok {
t.Fatalf("invalid chunk span provided (%d)", span)
}
binary.Write(buf, binary.LittleEndian, spanCode)
} else {
binary.Write(buf, binary.LittleEndian, uint8(chunk.FormatStandardGoTsz))
}
for _, val := range values {
binary.Write(buf, binary.LittleEndian, uint32(val))
}
buf.Write(b)
itgen, _ := chunk.NewGen(buf.Bytes(), ts)
return *itgen
}
func getConnectedChunks(t *testing.T, metric schema.AMKey) *CCache {
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, false)
itgen2 := getItgen(t, values, 1005, false)
itgen3 := getItgen(t, values, 1010, false)
itgen4 := getItgen(t, values, 1015, false)
itgen5 := getItgen(t, values, 1020, false)
cc.Add(metric, 0, itgen1)
cc.Add(metric, 1000, itgen2)
cc.Add(metric, 1005, itgen3)
cc.Add(metric, 1010, itgen4)
cc.Add(metric, 1015, itgen5)
return cc
}
func printMemUsage(wg *sync.WaitGroup) {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("HeapAlloc = %v MB\t %v KB\t %v B\n", (m.HeapAlloc / 1024 / 1024), (m.HeapAlloc / 1024), m.HeapAlloc)
fmt.Printf("TotalAlloc = %v MB\t %v KB\t %v B\n", (m.HeapAlloc / 1024 / 1024), (m.TotalAlloc / 1024), m.HeapAlloc)
fmt.Printf("Sys = %v MB\t %v KB\t %v B\n", (m.Sys / 1024 / 1024), (m.Sys / 1024), m.Sys)
fmt.Printf("Live Heap Objects = %v\n", (m.Mallocs - m.Frees))
fmt.Printf("NumGC = %v\n\n\n", m.NumGC)
wg.Done()
}
// test if evict has a memory leak under certain conditions
func TestEvictMemoryLeak(t *testing.T) {
wg := sync.WaitGroup{}
fmt.Println("Starting mem stats")
wg.Add(1)
printMemUsage(&wg)
wg.Wait()
metric1 := test.GetAMKey(1)
cc := NewCCache()
maxVals := 5
values := make([]uint32, 0, maxVals)
for i := 1; i <= maxVals; i++ {
values = append(values, uint32(i))
}
maxItgens := 50000
step := 5
initial := 1000
maxMinusOneItgens := (maxItgens * step) + (initial - step)
fmt.Println("maxItgens:", maxItgens)
fmt.Println("")
itgens1 := make([]chunk.IterGen, 0, maxItgens)
for i := initial; i < ((maxItgens * step) + initial); i += step {
itgens1 = append(itgens1, getItgen(t, values, uint32(i), true))
}
cc.AddRange(metric1, 0, itgens1)
runtime.GC()
mc, ok := cc.metricCache[metric1]
if !ok {
t.Fatal("metric doesn't exist in cc.metricCache")
}
fmt.Printf("len(mc.chunks): %v\n", len(mc.chunks))
time.Sleep(3 * time.Second)
fmt.Println("Stats after AddRange and values allocation")
wg.Add(1)
printMemUsage(&wg)
wg.Wait()
for i := initial; i < maxMinusOneItgens; i += step {
mc.Del(uint32(i))
}
fmt.Printf("len(mc.chunks): %v\n", len(mc.chunks))
runtime.GC()
time.Sleep(3 * time.Second)
wg.Add(1)
fmt.Println("Stats after deleted most chunks")
printMemUsage(&wg)
wg.Wait()
for _, chnk := range mc.chunks {
mc.Del(chnk.Ts)
}
fmt.Printf("len(mc.chunks): %v\n", len(mc.chunks))
runtime.GC()
time.Sleep(3 * time.Second)
fmt.Println("Stats after deleting all chunks")
wg.Add(1)
printMemUsage(&wg)
wg.Wait()
delete(cc.metricCache, metric1)
runtime.GC()
time.Sleep(3 * time.Second)
fmt.Println("Stats after deleting *CCacheMetric from *CCache")
wg.Add(1)
printMemUsage(&wg)
wg.Wait()
}
// test AddIfHot method without passing a previous timestamp on a hot metric
func TestAddIfHotWithoutPrevTsOnHotMetric(t *testing.T) {
metric := test.GetAMKey(1)
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, false)
itgen2 := getItgen(t, values, 1005, false)
itgen3 := getItgen(t, values, 1010, false)
cc.Add(metric, 0, itgen1)
cc.Add(metric, 1000, itgen2)
cc.AddIfHot(metric, 0, itgen3)
mc := cc.metricCache[metric]
chunk, ok := mc.chunks[1010]
if !ok {
t.Fatalf("expected cache chunk to have been cached")
}
if itgen3.Ts != chunk.Ts {
t.Fatalf("cached chunk wasn't the expected one")
}
if chunk.Prev != 1005 {
t.Fatalf("expected cache chunk's previous ts to be 1005, but got %d", chunk.Prev)
}
if mc.chunks[chunk.Prev].Next != chunk.Ts {
t.Fatalf("previous cache chunk didn't point at this one as it's next, got %d", mc.chunks[chunk.Prev].Next)
}
}
// test AddIfHot method without passing a previous timestamp on a cold metric
func TestAddIfHotWithoutPrevTsOnColdMetric(t *testing.T) {
metric := test.GetAMKey(1)
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, false)
itgen3 := getItgen(t, values, 1010, false)
cc.Add(metric, 0, itgen1)
cc.AddIfHot(metric, 0, itgen3)
mc := cc.metricCache[metric]
_, ok := mc.chunks[1010]
if ok {
t.Fatalf("expected cache chunk to not have been cached")
}
if mc.chunks[1000].Next != 0 {
t.Fatalf("previous cache chunk got wrongly connected with a following one, got %d", mc.chunks[1000].Next)
}
}
// test AddIfHot method on a hot metric
func TestAddIfHotWithPrevTsOnHotMetric(t *testing.T) {
metric := test.GetAMKey(1)
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, false)
itgen2 := getItgen(t, values, 1005, false)
itgen3 := getItgen(t, values, 1010, false)
cc.Add(metric, 0, itgen1)
cc.Add(metric, 1000, itgen2)
cc.AddIfHot(metric, 1005, itgen3)
mc := cc.metricCache[metric]
chunk, ok := mc.chunks[1010]
if !ok {
t.Fatalf("expected cache chunk to have been cached")
}
if itgen3.Ts != chunk.Ts {
t.Fatalf("cached chunk wasn't the expected one")
}
if chunk.Prev != 1005 {
t.Fatalf("expected cache chunk's previous ts to be 1005, but got %d", chunk.Prev)
}
if mc.chunks[chunk.Prev].Next != chunk.Ts {
t.Fatalf("previous cache chunk didn't point at this one as it's next, got %d", mc.chunks[chunk.Prev].Next)
}
}
// test AddIfHot method on a cold metric
func TestAddIfHotWithPrevTsOnColdMetric(t *testing.T) {
metric := test.GetAMKey(1)
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, false)
itgen3 := getItgen(t, values, 1010, false)
cc.Add(metric, 0, itgen1)
cc.AddIfHot(metric, 1005, itgen3)
mc := cc.metricCache[metric]
_, ok := mc.chunks[1010]
if ok {
t.Fatalf("expected cache chunk to not have been cached")
}
if mc.chunks[1000].Next != 0 {
t.Fatalf("previous cache chunk got wrongly connected with a following one, got %d", mc.chunks[1000].Next)
}
}
func TestConsecutiveAdding(t *testing.T) {
metric := test.GetAMKey(1)
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, false)
itgen2 := getItgen(t, values, 1005, false)
cc.Add(metric, 0, itgen1)
cc.Add(metric, 1000, itgen2)
mc := cc.metricCache[metric]
chunk1, ok := mc.chunks[1000]
if !ok {
t.Fatalf("expected cache chunk 1000 not found")
}
chunk2, ok := mc.chunks[1005]
if !ok {
t.Fatalf("expected cache chunk 2000 not found")
}
if chunk1.Prev != 0 {
t.Fatalf("Expected previous chunk to be 0, got %d", chunk1.Prev)
}
if chunk1.Next != 1005 {
t.Fatalf("Expected next chunk to be 2000, got %d", chunk1.Next)
}
if chunk2.Prev != 1000 {
t.Fatalf("Expected previous chunk to be 1000, got %d", chunk2.Prev)
}
if chunk2.Next != 0 {
t.Fatalf("Expected next chunk to be 0, got %d", chunk2.Next)
}
}
// tests if chunks get connected to previous even if it is is not specified, based on span
func TestDisconnectedAdding(t *testing.T) {
metric := test.GetAMKey(1)
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, true)
itgen2 := getItgen(t, values, 1005, true)
itgen3 := getItgen(t, values, 1010, true)
cc.Add(metric, 0, itgen1)
cc.Add(metric, 0, itgen2)
cc.Add(metric, 0, itgen3)
res, err := cc.Search(test.NewContext(), metric, 900, 1015)
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if res.Complete {
t.Fatalf("complete is expected to be false")
}
if len(res.Start) != 0 {
t.Fatalf("expected to get 0 itergens in Start, got %d", len(res.Start))
}
if len(res.End) != 3 {
t.Fatalf("expected to get 3 itergens in End, got %d", len(res.End))
}
if res.End[0].Ts != 1010 || res.End[len(res.End)-1].Ts != 1000 {
t.Fatalf("result set is wrong")
}
}
// tests if chunks get connected to previous even if it is is not specified,
// basesd on a span which is the result of a guess that's based on the distance to the previous chunk
func TestDisconnectedAddingByGuessing(t *testing.T) {
metric := test.GetAMKey(1)
cc := NewCCache()
values := []uint32{1, 2, 3, 4, 5}
itgen1 := getItgen(t, values, 1000, false)
itgen2 := getItgen(t, values, 1005, false)
itgen3 := getItgen(t, values, 1010, false)
cc.Add(metric, 0, itgen1)
cc.Add(metric, 1000, itgen2)
cc.Add(metric, 0, itgen3)
res, err := cc.Search(test.NewContext(), metric, 900, 1015)
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if res.Complete {
t.Fatalf("complete is expected to be false")
}
if len(res.Start) != 0 {
t.Fatalf("expected to get 0 itergens in Start, got %d", len(res.Start))
}
if len(res.End) != 3 {
t.Fatalf("expected to get 3 itergens in End, got %d", len(res.End))
}
if res.End[0].Ts != 1010 || res.End[len(res.End)-1].Ts != 1000 {
t.Fatalf("result set is wrong")
}
mc, ok := cc.metricCache[metric]
if !ok {
t.Fatalf("cannot find metric that should be present")
}
lastChunk, ok := mc.chunks[1010]
if !ok {
t.Fatalf("cannot find chunk that should be present")
}
if lastChunk.Prev != 1005 {
t.Fatalf("Add() method failed to correctly guess previous chunk")
}
}
func TestSearchFromBeginningComplete(t *testing.T) {
metric := test.GetAMKey(1)
cc := getConnectedChunks(t, metric)
res, err := cc.Search(test.NewContext(), metric, 1006, 1025)
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if !res.Complete {
t.Fatalf("complete is expected to be true")
}
if len(res.Start) != 4 {
t.Fatalf("expected to get 4 itergens, got %d", len(res.Start))
}
if res.Start[0].Ts != 1005 || res.Start[len(res.Start)-1].Ts != 1020 {
t.Fatalf("result set is wrong")
}
}
func TestSearchFromBeginningIncompleteEnd(t *testing.T) {
metric := test.GetAMKey(1)
cc := getConnectedChunks(t, metric)
res, err := cc.Search(test.NewContext(), metric, 1006, 1030)
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if res.Complete {
t.Fatalf("complete is expected to be false")
}
if len(res.Start) != 4 {
t.Fatalf("expected to get 4 itergens, got %d", len(res.Start))
}
if res.Start[0].Ts != 1005 || res.Start[len(res.Start)-1].Ts != 1020 {
t.Fatalf("result set is wrong")
}
}
func TestSearchFromEnd(t *testing.T) {
metric := test.GetAMKey(1)
cc := getConnectedChunks(t, metric)
res, err := cc.Search(test.NewContext(), metric, 500, 1025)
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if res.Complete {
t.Fatalf("complete is expected to not be true")
}
if res.From != 500 {
t.Fatalf("From is expected to remain the original value")
}
if len(res.End) != 5 {
t.Fatalf("expected to get 5 itergens, got %d", len(res.End))
}
if res.Until != 1000 {
t.Fatalf("Until is expected to be 1000, got %d", res.Until)
}
if res.End[0].Ts != 1020 || res.End[len(res.End)-1].Ts != 1000 {
t.Fatalf("result set is wrong")
}
}
func TestSearchDisconnectedStartEndSpanawareAscending(t *testing.T) {
testSearchDisconnectedStartEnd(t, true, true)
}
func TestSearchDisconnectedStartEndSpanawareDescending(t *testing.T) {
testSearchDisconnectedStartEnd(t, true, false)
}
func TestSearchDisconnectedStartEndNonSpanaware(t *testing.T) {
testSearchDisconnectedStartEnd(t, false, true)
}
func testSearchDisconnectedStartEnd(t *testing.T, spanaware, ascending bool) {
metric := test.GetAMKey(1)
values := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
itgen1 := getItgen(t, values, 1000, spanaware)
itgen2 := getItgen(t, values, 1010, spanaware)
itgen3 := getItgen(t, values, 1020, spanaware)
itgen4 := getItgen(t, values, 1030, spanaware)
itgen5 := getItgen(t, values, 1040, spanaware)
itgen6 := getItgen(t, values, 1050, spanaware)
cc := NewCCache()
for from := uint32(1000); from < 1010; from++ {
// the end of ranges is exclusive, so we go up to 1060
for until := uint32(1051); until < 1061; until++ {
cc.Reset()
if ascending {
cc.Add(metric, 0, itgen1)
cc.Add(metric, 1000, itgen2)
cc.Add(metric, 1010, itgen3)
cc.Add(metric, 0, itgen4)
cc.Add(metric, 1030, itgen5)
cc.Add(metric, 1040, itgen6)
} else {
cc.Add(metric, 0, itgen6)
cc.Add(metric, 0, itgen5)
cc.Add(metric, 0, itgen4)
cc.Add(metric, 0, itgen3)
cc.Add(metric, 0, itgen2)
cc.Add(metric, 0, itgen1)
}
res, err := cc.Search(test.NewContext(), metric, from, until)
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if !res.Complete {
t.Fatalf("from %d, until %d: complete is expected to be true", from, until)
}
if len(res.Start) != 6 {
t.Fatalf("from %d, until %d: expected to get %d itergens at start, got %d", from, until, 6, len(res.Start))
}
if res.Start[0].Ts != 1000 || res.Start[len(res.Start)-1].Ts != 1050 {
t.Fatalf("from %d, until %d: result set at Start is wrong", from, until)
}
if res.From != 1060 {
t.Fatalf("from %d, until %d: expected From to be %d, got %d", from, until, 1060, res.From)
}
if len(res.End) != 0 {
t.Fatalf("from %d, until %d: expected to get %d itergens at end, got %d", from, until, 0, len(res.End))
}
if res.Until != until {
t.Fatalf("from %d, until %d: expected Until to be %d, got %d", from, until, 1055, res.Until)
}
}
}
}
func TestSearchDisconnectedWithGapStartEndSpanawareAscending(t *testing.T) {
testSearchDisconnectedWithGapStartEnd(t, true, true)
}
func TestSearchDisconnectedWithGapStartEndSpanawareDescending(t *testing.T) {
testSearchDisconnectedWithGapStartEnd(t, true, false)
}
func TestSearchDisconnectedWithGapStartEndNonSpanaware(t *testing.T) {
testSearchDisconnectedWithGapStartEnd(t, false, true)
}
func testSearchDisconnectedWithGapStartEnd(t *testing.T, spanaware, ascending bool) {
metric := test.GetAMKey(1)
values := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
itgen1 := getItgen(t, values, 1000, spanaware)
itgen2 := getItgen(t, values, 1010, spanaware)
itgen3 := getItgen(t, values, 1020, spanaware)
// missing chunk
itgen4 := getItgen(t, values, 1040, spanaware)
itgen5 := getItgen(t, values, 1050, spanaware)
itgen6 := getItgen(t, values, 1060, spanaware)
cc := NewCCache()
for from := uint32(1000); from < 1010; from++ {
// the end of ranges is exclusive, so we go up to 1060
for until := uint32(1061); until < 1071; until++ {
cc.Reset()
if ascending {
cc.Add(metric, 0, itgen1)
cc.Add(metric, 1000, itgen2)
cc.Add(metric, 1010, itgen3)
cc.Add(metric, 0, itgen4)
cc.Add(metric, 1040, itgen5)
cc.Add(metric, 1050, itgen6)
} else {
cc.Add(metric, 0, itgen6)
cc.Add(metric, 0, itgen5)
cc.Add(metric, 0, itgen4)
cc.Add(metric, 0, itgen3)
cc.Add(metric, 0, itgen2)
cc.Add(metric, 0, itgen1)
}
res, err := cc.Search(test.NewContext(), metric, from, until)
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if res.Complete {
t.Fatalf("from %d, until %d: complete is expected to be false", from, until)
}
if len(res.Start) != 3 {
t.Fatalf("from %d, until %d: expected to get 3 itergens at start, got %d", from, until, len(res.Start))
}
if res.Start[0].Ts != 1000 || res.Start[len(res.Start)-1].Ts != 1020 {
t.Fatalf("from %d, until %d: result set at Start is wrong", from, until)
}
if res.From != 1030 {
t.Fatalf("from %d, until %d: expected From to be %d but got %d", from, until, 1030, res.From)
}
if len(res.End) != 3 {
t.Fatalf("from %d, until %d: expected to get 3 itergens at end, got %d", from, until, len(res.End))
}
if res.End[0].Ts != 1060 || res.End[len(res.End)-1].Ts != 1040 {
t.Fatalf("from %d, until %d: result set at End is wrong", from, until)
}
if res.Until != 1040 {
t.Fatalf("from %d, until %d: expected Until to be %d but got %d", from, until, 1030, res.Until)
}
}
}
}
func TestReset(t *testing.T) {
cc := NewCCache()
// .Reset() is being called at the end of testMetricDelete()
testMetricDelete(t, cc)
testMetricDelete(t, cc)
testMetricDelete(t, cc)
}
func TestMetricDelete(t *testing.T) {
cc := NewCCache()
testMetricDelete(t, cc)
}
func testMetricDelete(t *testing.T, cc *CCache) {
rawMetric1 := test.GetAMKey(1)
metric1_1 := schema.GetAMKey(rawMetric1.MKey, schema.Cnt, 600)
metric1_2 := schema.GetAMKey(rawMetric1.MKey, schema.Sum, 600)
rawMetric2 := test.GetMKey(2)
metric2_1 := schema.GetAMKey(rawMetric2, schema.Cnt, 6000)
values := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
itgenCount := 10
itgens := make([]chunk.IterGen, 0, itgenCount)
for i := 1000; i < 1000+itgenCount*len(values); i = i + len(values) {
itgens = append(itgens, getItgen(t, values, uint32(i), true))
}
// add two metrics with itgenCount chunks each
for _, itgen := range itgens {
cc.Add(metric1_1, 0, itgen)
cc.Add(metric1_2, 0, itgen)
cc.Add(metric2_1, 0, itgen)
}
// check if Search returns them all for metric1_1
res, err := cc.Search(test.NewContext(), metric1_1, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != itgenCount {
t.Fatalf("Expected to have %d values, got %d", itgenCount, len(res.Start))
}
// check if Search returns them all for metric1_2
res, err = cc.Search(test.NewContext(), metric1_2, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != itgenCount {
t.Fatalf("Expected to have %d values, got %d", itgenCount, len(res.Start))
}
// check if Search returns them all for metric2_1
res, err = cc.Search(test.NewContext(), metric2_1, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != itgenCount {
t.Fatalf("Expected to have %d values, got %d", itgenCount, len(res.Start))
}
// now delete metric1_1, but leave metric2_1
delSeries, delArchives := cc.DelMetric(rawMetric1.MKey)
expectDelSeries := 1
if delSeries != expectDelSeries {
t.Fatalf("Expected exactly %d deleted series, but got %d", expectDelSeries, delSeries)
}
expectDelArchives := 2
if delArchives != expectDelArchives {
t.Fatalf("Expected exactly %d deleted archives, but got %d", expectDelArchives, delArchives)
}
// check if metric1_1 returns no results anymore
res, err = cc.Search(test.NewContext(), metric1_1, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != 0 {
t.Fatalf("Expected to have %d values, got %d", 0, len(res.Start))
}
// check if metric1_2 returns no results anymore
res, err = cc.Search(test.NewContext(), metric1_2, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != 0 {
t.Fatalf("Expected to have %d values, got %d", 0, len(res.Start))
}
// but metric2_1 should still be there
res, err = cc.Search(test.NewContext(), metric2_1, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != itgenCount {
t.Fatalf("Expected to have %d values, got %d", itgenCount, len(res.Start))
}
// now add metric1_1 and metric1_2 again
for _, itgen := range itgens {
cc.Add(metric1_1, 0, itgen)
cc.Add(metric1_2, 0, itgen)
}
// and check if it gets returned by Search again
res, err = cc.Search(test.NewContext(), metric1_1, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != itgenCount {
t.Fatalf("Expected to have %d values, got %d", itgenCount, len(res.Start))
}
// now reset the whole metric cache
delSeries, delArchives = cc.Reset()
expectDelSeries = 2
if delSeries != expectDelSeries {
t.Fatalf("Expected exactly deleted %d series, but got %d", expectDelSeries, delSeries)
}
expectDelArchives = 3
if delArchives != expectDelArchives {
t.Fatalf("Expected exactly deleted %d archives, but got %d", expectDelArchives, delArchives)
}
// check if metric1_1 returns no results anymore
res, err = cc.Search(test.NewContext(), metric1_1, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != 0 {
t.Fatalf("Expected to have %d values, got %d", 0, len(res.Start))
}
// check if metric1_1 returns no results anymore
res, err = cc.Search(test.NewContext(), metric1_2, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != 0 {
t.Fatalf("Expected to have %d values, got %d", 0, len(res.Start))
}
// check if metric2_1 returns no results anymore
res, err = cc.Search(test.NewContext(), metric2_1, 1000, uint32(1000+itgenCount*len(values)))
if err != nil {
t.Fatalf("expected err nil, got %v", err)
}
if len(res.Start) != 0 {
t.Fatalf("Expected to have %d values, got %d", 0, len(res.Start))
}
}
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1502 KB 1538616 B
TotalAlloc = 1 MB 1502 KB 1538616 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1189
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24474 KB 25062304 B
TotalAlloc = 23 MB 30823 KB 25062304 B
Sys = 68 MB 70142 KB 71825656 B
Live Heap Objects = 205693
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 13 MB 13387 KB 13709216 B
TotalAlloc = 13 MB 5093251 KB 13709216 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103587
NumGC = 298
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13387 KB 13709032 B
TotalAlloc = 13 MB 5093252 KB 13709032 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103583
NumGC = 299
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12346 KB 12642648 B
TotalAlloc = 12 MB 5093253 KB 12642648 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102763
NumGC = 300
--- PASS: TestEvictMemoryLeak (256.52s)
PASS
ok github.com/grafana/metrictank/mdata/cache 256.540s
*************************************************************************************************
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1501 KB 1537712 B
TotalAlloc = 1 MB 1501 KB 1537712 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1190
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24497 KB 25085064 B
TotalAlloc = 23 MB 30843 KB 25085064 B
Sys = 68 MB 70398 KB 72087800 B
Live Heap Objects = 205773
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 13 MB 13396 KB 13718088 B
TotalAlloc = 13 MB 5093273 KB 13718088 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103608
NumGC = 298
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13396 KB 13717976 B
TotalAlloc = 13 MB 5093274 KB 13717976 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103606
NumGC = 299
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12357 KB 12653848 B
TotalAlloc = 12 MB 5093275 KB 12653848 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102807
NumGC = 300
--- PASS: TestEvictMemoryLeak (255.20s)
PASS
ok github.com/grafana/metrictank/mdata/cache 255.326s
*************************************************************************************************
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1500 KB 1536352 B
TotalAlloc = 1 MB 1500 KB 1536352 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1181
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24481 KB 25069016 B
TotalAlloc = 23 MB 30831 KB 25069016 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 205713
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 13 MB 13353 KB 13673968 B
TotalAlloc = 13 MB 5093225 KB 13673968 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103598
NumGC = 298
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13353 KB 13673792 B
TotalAlloc = 13 MB 5093226 KB 13673792 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103595
NumGC = 299
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12308 KB 12604160 B
TotalAlloc = 12 MB 5093227 KB 12604160 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102746
NumGC = 300
--- PASS: TestEvictMemoryLeak (248.36s)
PASS
ok github.com/grafana/metrictank/mdata/cache 248.379s
*************************************************************************************************
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1500 KB 1536336 B
TotalAlloc = 1 MB 1500 KB 1536336 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1186
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24475 KB 25063000 B
TotalAlloc = 23 MB 30821 KB 25063000 B
Sys = 68 MB 70398 KB 72087800 B
Live Heap Objects = 205657
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 13 MB 13370 KB 13691192 B
TotalAlloc = 13 MB 5093235 KB 13691192 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103548
NumGC = 297
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13370 KB 13691016 B
TotalAlloc = 13 MB 5093236 KB 13691016 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103545
NumGC = 298
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12326 KB 12622728 B
TotalAlloc = 12 MB 5093236 KB 12622728 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102708
NumGC = 299
--- PASS: TestEvictMemoryLeak (251.36s)
PASS
ok github.com/grafana/metrictank/mdata/cache 251.379s
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1501 KB 1537296 B
TotalAlloc = 1 MB 1501 KB 1537296 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1181
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24462 KB 25049264 B
TotalAlloc = 23 MB 30809 KB 25049264 B
Sys = 68 MB 70398 KB 72087800 B
Live Heap Objects = 155605
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 20 MB 21203 KB 21712592 B
TotalAlloc = 20 MB 5093243 KB 21712592 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 153552
NumGC = 260
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13390 KB 13712336 B
TotalAlloc = 13 MB 5093244 KB 13712336 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103551
NumGC = 261
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12346 KB 12642808 B
TotalAlloc = 12 MB 5093245 KB 12642808 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102702
NumGC = 262
--- PASS: TestEvictMemoryLeak (260.05s)
PASS
ok github.com/grafana/metrictank/mdata/cache 260.074s
*************************************************************************************************
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1500 KB 1536960 B
TotalAlloc = 1 MB 1500 KB 1536960 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1182
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24205 KB 24786424 B
TotalAlloc = 23 MB 30837 KB 24786424 B
Sys = 68 MB 70398 KB 72087800 B
Live Heap Objects = 155464
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 20 MB 21187 KB 21696400 B
TotalAlloc = 20 MB 5093252 KB 21696400 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 153587
NumGC = 260
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13375 KB 13696120 B
TotalAlloc = 13 MB 5093253 KB 13696120 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103584
NumGC = 261
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12330 KB 12626904 B
TotalAlloc = 12 MB 5093254 KB 12626904 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102740
NumGC = 262
--- PASS: TestEvictMemoryLeak (257.12s)
PASS
ok github.com/grafana/metrictank/mdata/cache 257.138s
*************************************************************************************************
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1501 KB 1537488 B
TotalAlloc = 1 MB 1501 KB 1537488 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1193
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24482 KB 25070432 B
TotalAlloc = 23 MB 30828 KB 25070432 B
Sys = 68 MB 70398 KB 72087800 B
Live Heap Objects = 155676
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 20 MB 21225 KB 21735168 B
TotalAlloc = 20 MB 5093274 KB 21735168 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 153590
NumGC = 260
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13412 KB 13734896 B
TotalAlloc = 13 MB 5093275 KB 13734896 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103588
NumGC = 261
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12372 KB 12669408 B
TotalAlloc = 12 MB 5093276 KB 12669408 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102776
NumGC = 262
--- PASS: TestEvictMemoryLeak (256.27s)
PASS
ok github.com/grafana/metrictank/mdata/cache 256.301s
*************************************************************************************************
=== RUN TestEvictMemoryLeak
Starting mem stats
HeapAlloc = 1 MB 1501 KB 1537144 B
TotalAlloc = 1 MB 1501 KB 1537144 B
Sys = 68 MB 69694 KB 71366904 B
Live Heap Objects = 1187
NumGC = 0
maxItgens: 50000
len(mc.chunks): 50000
Stats after AddRange and values allocation
HeapAlloc = 23 MB 24471 KB 25058712 B
TotalAlloc = 23 MB 30817 KB 25058712 B
Sys = 68 MB 70398 KB 72087800 B
Live Heap Objects = 155612
NumGC = 4
len(mc.chunks): 1
Stats after deleted most chunks
HeapAlloc = 20 MB 21202 KB 21711304 B
TotalAlloc = 20 MB 5093244 KB 21711304 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 153558
NumGC = 260
len(mc.chunks): 0
Stats after deleting all chunks
HeapAlloc = 13 MB 13389 KB 13711024 B
TotalAlloc = 13 MB 5093244 KB 13711024 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 103555
NumGC = 261
Stats after deleting *CCacheMetric from *CCache
HeapAlloc = 12 MB 12349 KB 12645536 B
TotalAlloc = 12 MB 5093245 KB 12645536 B
Sys = 68 MB 70654 KB 72349944 B
Live Heap Objects = 102743
NumGC = 262
--- PASS: TestEvictMemoryLeak (257.20s)
PASS
ok github.com/grafana/metrictank/mdata/cache 257.217s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment