Skip to content

Commit d044cbd

Browse files
committed
Load Test BadgerGC
Signed-off-by: leigh capili <[email protected]>
1 parent b162d0f commit d044cbd

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

internal/database/badger_gc_test.go

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,19 @@ package database
1717

1818
import (
1919
"context"
20+
"fmt"
2021
"os"
22+
"regexp"
2123
"testing"
2224
"time"
2325

2426
"github.com/dgraph-io/badger/v4"
2527
"github.com/go-logr/logr"
2628
"github.com/go-logr/logr/testr"
29+
"github.com/pkg/errors"
30+
31+
"github.com/google/go-containerregistry/pkg/name"
32+
"github.com/google/go-containerregistry/pkg/v1/remote"
2733
)
2834

2935
func TestBadgerGarbageCollectorDoesStop(t *testing.T) {
@@ -60,13 +66,88 @@ func TestBadgerGarbageCollectorDoesStop(t *testing.T) {
6066
}
6167
}
6268

69+
func TestBadgerGCLoad(t *testing.T) {
70+
badger, db := createBadgerDatabaseForGC(t)
71+
ctx, cancel := context.WithCancel(
72+
logr.NewContext(context.Background(), testr.NewWithOptions(t, testr.Options{Verbosity: 1, LogTimestamp: true})))
73+
74+
stop := make(chan struct{})
75+
go func() {
76+
gc := NewBadgerGarbageCollector("loaded-badger-gc", badger, time.Second*20, 0.7)
77+
gc.Start(ctx)
78+
stop <- struct{}{}
79+
}()
80+
81+
repos := []string{"alpine", "node", "postgres", "debian"}
82+
for i := 5; i >= 0; i-- {
83+
for _, repo := range repos {
84+
ref, err := name.ParseReference(repo)
85+
fatalIfError(t, err)
86+
tags, err := remote.List(ref.Context())
87+
iter := (i + 3) * 15000
88+
for r := 0; r <= iter; r++ {
89+
fatalIfError(t, err)
90+
db.SetTags(fmt.Sprintf("%s-%d", repo, r), tags[0:len(tags)-i])
91+
// time.Sleep(time.Millisecond)
92+
}
93+
t.Logf("%s %d: %d repos", repo, i, iter)
94+
}
95+
time.Sleep(time.Millisecond * 100)
96+
}
97+
98+
cancel()
99+
t.Log("waiting for GC stop")
100+
select {
101+
case <-time.NewTimer(30 * time.Second).C:
102+
t.Fatalf("GC did not stop")
103+
case <-stop:
104+
t.Log("GC Stopped")
105+
}
106+
}
107+
108+
type badgerTestLogger struct {
109+
logger logr.Logger
110+
}
111+
112+
func (l *badgerTestLogger) Errorf(f string, v ...interface{}) {
113+
l.logger.Error(errors.Errorf("ERROR: "+f, v...), f)
114+
}
115+
func (l *badgerTestLogger) Infof(f string, v ...interface{}) {
116+
l.log("INFO", f, v...)
117+
}
118+
func (l *badgerTestLogger) Warningf(f string, v ...interface{}) {
119+
l.log("WARNING", f, v...)
120+
}
121+
func (l *badgerTestLogger) Debugf(f string, v ...interface{}) {
122+
l.log("DEBUG", f, v...)
123+
}
124+
125+
var filter = regexp.MustCompile(`writeRequests called. Writing to value log|2 entries written|Writing to memtable|Sending updates to subscribers|Found value log max|fid:|Moved: 0|Processed 0 entries in 0 loops|Discard stats: map`)
126+
127+
func (l *badgerTestLogger) log(lvl string, f string, v ...interface{}) {
128+
str := fmt.Sprintf(lvl+": "+f, v...)
129+
if filter.MatchString(str) {
130+
return
131+
}
132+
l.logger.Info(str)
133+
}
134+
63135
func createBadgerDatabaseForGC(t *testing.T) (*badger.DB, *BadgerDatabase) {
64136
t.Helper()
65137
dir, err := os.MkdirTemp(os.TempDir(), t.Name())
66138
if err != nil {
67139
t.Fatal(err)
68140
}
69-
db, err := badger.Open(badger.DefaultOptions(dir))
141+
opts := badger.DefaultOptions(dir)
142+
opts = opts.WithValueThreshold(100) // force values into the vlog files
143+
opts = opts.WithValueLogMaxEntries(1000) // force many vlogs to be created
144+
opts = opts.WithValueLogFileSize(32 << 19)
145+
opts = opts.WithMemTableSize(16 << 19) // fill up memtables quickly
146+
opts = opts.WithNumMemtables(1)
147+
opts = opts.WithNumLevelZeroTables(1) // hold fewer memtables in memory
148+
opts = opts.WithLogger(&badgerTestLogger{logger: testr.NewWithOptions(t, testr.Options{LogTimestamp: true})})
149+
// opts = opts.WithLoggingLevel(badger.DEBUG)
150+
db, err := badger.Open(opts)
70151
if err != nil {
71152
t.Fatal(err)
72153
}

0 commit comments

Comments
 (0)