Skip to content

Commit

Permalink
Refactored Eviction framework with Basic LRU based Batch Eviction
Browse files Browse the repository at this point in the history
Signed-off-by: soumya-codes <[email protected]>
  • Loading branch information
soumya-codes committed Nov 12, 2024
1 parent 51ccd04 commit 2854dab
Show file tree
Hide file tree
Showing 23 changed files with 495 additions and 434 deletions.
38 changes: 18 additions & 20 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ const (
DefaultConfigName string = "dice.toml"
DefaultConfigFilePath string = "./"

EvictSimpleFirst = "simple-first"
EvictAllKeysRandom = "allkeys-random"
EvictAllKeysLRU = "allkeys-lru"
EvictAllKeysLFU = "allkeys-lfu"
EvictBatchKeysLRU string = "batch_keys_lru"

DefaultKeysLimit int = 200000000
DefaultKeysLimit int = 200000000
DefaultEvictionRatio float64 = 0.1
)

var (
Expand Down Expand Up @@ -97,11 +95,11 @@ type Config struct {
} `mapstructure:"performance"`

Memory struct {
MaxMemory int64 `mapstructure:"maxmemory"`
EvictionPolicy string `mapstructure:"evictionpolicy"`
EvictionRatio float64 `mapstructure:"evictionratio"`
KeysLimit int `mapstructure:"keyslimit"`
LFULogFactor int `mapstructure:"lfulogfactor"`
MaxMemory int64 `mapstructure:"maxmemory"`
EvictionStrategy string `mapstructure:"evictionstrategy"`
EvictionRatio float64 `mapstructure:"evictionratio"`
KeysLimit int `mapstructure:"keyslimit"`
LFULogFactor int `mapstructure:"lfulogfactor"`
} `mapstructure:"memory"`

Persistence struct {
Expand Down Expand Up @@ -181,17 +179,17 @@ var baseConfig = Config{
AdhocReqChanBufSize: 20, // assuming we wouldn't have more than 20 adhoc requests being sent at a time.
},
Memory: struct {
MaxMemory int64 `mapstructure:"maxmemory"`
EvictionPolicy string `mapstructure:"evictionpolicy"`
EvictionRatio float64 `mapstructure:"evictionratio"`
KeysLimit int `mapstructure:"keyslimit"`
LFULogFactor int `mapstructure:"lfulogfactor"`
MaxMemory int64 `mapstructure:"maxmemory"`
EvictionStrategy string `mapstructure:"evictionstrategy"`
EvictionRatio float64 `mapstructure:"evictionratio"`
KeysLimit int `mapstructure:"keyslimit"`
LFULogFactor int `mapstructure:"lfulogfactor"`
}{
MaxMemory: 0,
EvictionPolicy: EvictAllKeysLFU,
EvictionRatio: 0.9,
KeysLimit: DefaultKeysLimit,
LFULogFactor: 10,
MaxMemory: 0,
EvictionStrategy: EvictBatchKeysLRU,
EvictionRatio: DefaultEvictionRatio,
KeysLimit: DefaultKeysLimit,
LFULogFactor: 10,
},
Persistence: struct {
AOFFile string `mapstructure:"aoffile"`
Expand Down
4 changes: 2 additions & 2 deletions internal/eval/bloom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

func TestBloomFilter(t *testing.T) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
// This test only contains some basic checks for all the bloom filter
// operations like BFRESERVE, BFADD, BFEXISTS. It assumes that the
// functions called in the main function are working correctly and
Expand Down Expand Up @@ -94,7 +94,7 @@ func TestBloomFilter(t *testing.T) {
}

func TestGetOrCreateBloomFilter(t *testing.T) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
// Create a key and default opts
key := "bf"
opts := defaultBloomOpts()
Expand Down
8 changes: 0 additions & 8 deletions internal/eval/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,13 +432,6 @@ var (
Eval: evalLATENCY,
Arity: -2,
}
lruCmdMeta = DiceCmdMeta{
Name: "LRU",
Info: `LRU deletes all the keys from the LRU
returns encoded RESP OK`,
Eval: evalLRU,
Arity: 1,
}
sleepCmdMeta = DiceCmdMeta{
Name: "SLEEP",
Info: `SLEEP sets db to sleep for the specified number of seconds.
Expand Down Expand Up @@ -1454,7 +1447,6 @@ func init() {
DiceCmds["LLEN"] = llenCmdMeta
DiceCmds["LPOP"] = lpopCmdMeta
DiceCmds["LPUSH"] = lpushCmdMeta
DiceCmds["LRU"] = lruCmdMeta
DiceCmds["MGET"] = MGetCmdMeta
DiceCmds["MSET"] = msetCmdMeta
DiceCmds["MULTI"] = MultiCmdMeta
Expand Down
2 changes: 1 addition & 1 deletion internal/eval/countminsketch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func TestCountMinSketch(t *testing.T) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

testCMSInitByDim(t, store)
testCMSInitByProb(t, store)
Expand Down
7 changes: 0 additions & 7 deletions internal/eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1064,13 +1064,6 @@ func evalLATENCY(args []string, store *dstore.Store) []byte {
return clientio.Encode([]string{}, false)
}

// evalLRU deletes all the keys from the LRU
// returns encoded RESP OK
func evalLRU(args []string, store *dstore.Store) []byte {
dstore.EvictAllkeysLRUOrLFU(store)
return clientio.RespOK
}

// evalSLEEP sets db to sleep for the specified number of seconds.
// The sleep time should be the only param in args.
// Returns error response if the time param in args is not of integer format.
Expand Down
58 changes: 28 additions & 30 deletions internal/eval/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,15 @@ import (
"testing"
"time"

"github.com/dicedb/dice/internal/eval/sortedset"
"github.com/dicedb/dice/internal/server/utils"

"github.com/bytedance/sonic"
"github.com/ohler55/ojg/jp"

"github.com/axiomhq/hyperloglog"
"github.com/bytedance/sonic"
"github.com/dicedb/dice/internal/clientio"
diceerrors "github.com/dicedb/dice/internal/errors"
"github.com/dicedb/dice/internal/eval/sortedset"
"github.com/dicedb/dice/internal/object"
"github.com/dicedb/dice/internal/server/utils"
dstore "github.com/dicedb/dice/internal/store"
"github.com/ohler55/ojg/jp"
"github.com/stretchr/testify/assert"
)

Expand All @@ -42,7 +40,7 @@ func setupTest(store *dstore.Store) *dstore.Store {
}

func TestEval(t *testing.T) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

testEvalMSET(t, store)
testEvalECHO(t, store)
Expand Down Expand Up @@ -1568,7 +1566,7 @@ func testEvalJSONOBJLEN(t *testing.T, store *dstore.Store) {

func BenchmarkEvalJSONOBJLEN(b *testing.B) {
sizes := []int{0, 10, 100, 1000, 10000, 100000} // Various sizes of JSON objects
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

for _, size := range sizes {
b.Run(fmt.Sprintf("JSONObjectSize_%d", size), func(b *testing.B) {
Expand Down Expand Up @@ -3938,13 +3936,13 @@ func runMigratedEvalTests(t *testing.T, tests map[string]evalTestCase, evalFunc
func BenchmarkEvalMSET(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
evalMSET([]string{"KEY", "VAL", "KEY2", "VAL2"}, store)
}
}

func BenchmarkEvalHSET(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
for i := 0; i < b.N; i++ {
evalHSET([]string{"KEY", fmt.Sprintf("FIELD_%d", i), fmt.Sprintf("VALUE_%d", i)}, store)
}
Expand Down Expand Up @@ -4237,7 +4235,7 @@ func testEvalHKEYS(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalHKEYS(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

for i := 0; i < b.N; i++ {
evalHSET([]string{"KEY", fmt.Sprintf("FIELD_%d", i), fmt.Sprintf("VALUE_%d", i)}, store)
Expand All @@ -4249,7 +4247,7 @@ func BenchmarkEvalHKEYS(b *testing.B) {
}

func BenchmarkEvalPFCOUNT(b *testing.B) {
store := *dstore.NewStore(nil, nil)
store := *dstore.NewStore(nil, nil, nil)

// Helper function to create and insert HLL objects
createAndInsertHLL := func(key string, items []string) {
Expand Down Expand Up @@ -4596,7 +4594,7 @@ func testEvalHLEN(t *testing.T, store *dstore.Store) {

func BenchmarkEvalHLEN(b *testing.B) {
sizes := []int{0, 10, 100, 1000, 10000, 100000}
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

for _, size := range sizes {
b.Run(fmt.Sprintf("HashSize_%d", size), func(b *testing.B) {
Expand Down Expand Up @@ -4908,7 +4906,7 @@ func testEvalTYPE(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalTYPE(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

// Define different types of objects to benchmark
objectTypes := map[string]func(){
Expand Down Expand Up @@ -5252,7 +5250,7 @@ func testEvalJSONOBJKEYS(t *testing.T, store *dstore.Store) {

func BenchmarkEvalJSONOBJKEYS(b *testing.B) {
sizes := []int{0, 10, 100, 1000, 10000, 100000} // Various sizes of JSON objects
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

for _, size := range sizes {
b.Run(fmt.Sprintf("JSONObjectSize_%d", size), func(b *testing.B) {
Expand Down Expand Up @@ -5510,7 +5508,7 @@ func testEvalGETRANGE(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalGETRANGE(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
store.Put("BENCHMARK_KEY", store.NewObj("Hello World", maxExDuration, object.ObjTypeString, object.ObjEncodingRaw))

inputs := []struct {
Expand All @@ -5535,7 +5533,7 @@ func BenchmarkEvalGETRANGE(b *testing.B) {
}

func BenchmarkEvalHSETNX(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
for i := 0; i < b.N; i++ {
evalHSETNX([]string{"KEY", fmt.Sprintf("FIELD_%d", i/2), fmt.Sprintf("VALUE_%d", i)}, store)
}
Expand Down Expand Up @@ -5638,15 +5636,15 @@ func testEvalHSETNX(t *testing.T, store *dstore.Store) {
runMigratedEvalTests(t, tests, evalHSETNX, store)
}
func TestMSETConsistency(t *testing.T) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
evalMSET([]string{"KEY", "VAL", "KEY2", "VAL2"}, store)

assert.Equal(t, "VAL", store.Get("KEY").Value)
assert.Equal(t, "VAL2", store.Get("KEY2").Value)
}

func BenchmarkEvalHINCRBY(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

// creating new fields
for i := 0; i < b.N; i++ {
Expand Down Expand Up @@ -5898,7 +5896,7 @@ func testEvalSETEX(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalSETEX(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

b.ResetTimer()
for i := 0; i < b.N; i++ {
Expand Down Expand Up @@ -6077,7 +6075,7 @@ func testEvalINCRBYFLOAT(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalINCRBYFLOAT(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
store.Put("key1", store.NewObj("1", maxExDuration, object.ObjTypeString, object.ObjEncodingEmbStr))
store.Put("key2", store.NewObj("1.2", maxExDuration, object.ObjTypeString, object.ObjEncodingEmbStr))

Expand Down Expand Up @@ -6316,7 +6314,7 @@ func testEvalBITOP(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalBITOP(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

// Setup initial data for benchmarking
store.Put("key1", store.NewObj(&ByteArray{data: []byte{0x01, 0x02, 0xff}}, maxExDuration, object.ObjTypeByteArray, object.ObjEncodingByteArray))
Expand Down Expand Up @@ -6630,7 +6628,7 @@ func testEvalAPPEND(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalAPPEND(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
for i := 0; i < b.N; i++ {
evalAPPEND([]string{"key", fmt.Sprintf("val_%d", i)}, store)
}
Expand Down Expand Up @@ -7358,7 +7356,7 @@ func BenchmarkEvalZPOPMIN(b *testing.B) {
},
}

store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

for _, bm := range benchmarks {
b.Run(bm.name, func(b *testing.B) {
Expand Down Expand Up @@ -7524,7 +7522,7 @@ func testEvalZREM(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalZRANK(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

// Set up initial sorted set
evalZADD([]string{"myzset", "1", "member1", "2", "member2", "3", "member3"}, store)
Expand Down Expand Up @@ -7806,7 +7804,7 @@ func testEvalHINCRBYFLOAT(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalHINCRBYFLOAT(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

// Setting initial fields with some values
store.Put("key1", store.NewObj(HashMap{"field1": "1.0", "field2": "1.2"}, maxExDuration, object.ObjTypeHashMap, object.ObjEncodingHashMap))
Expand Down Expand Up @@ -8164,7 +8162,7 @@ func testEvalJSONSTRAPPEND(t *testing.T, store *dstore.Store) {
}

func BenchmarkEvalJSONSTRAPPEND(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

// Setup a sample JSON document
key := "doc1"
Expand Down Expand Up @@ -8288,7 +8286,7 @@ func BenchmarkEvalZPOPMAX(b *testing.B) {
},
}

store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

for _, bm := range benchmarks {
b.Run(bm.name, func(b *testing.B) {
Expand All @@ -8304,7 +8302,7 @@ func BenchmarkEvalZPOPMAX(b *testing.B) {
}
}
func BenchmarkZCOUNT(b *testing.B) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)

// Populate the sorted set with some members for basic benchmarks
evalZADD([]string{"key", "10", "member1", "20", "member2", "30", "member3"}, store)
Expand Down Expand Up @@ -8333,7 +8331,7 @@ func BenchmarkZCOUNT(b *testing.B) {
// Benchmark for edge cases
b.Run("Edge Case ZCOUNT", func(b *testing.B) {
// Reset the store and set up members
store = dstore.NewStore(nil, nil)
store = dstore.NewStore(nil, nil, nil)
evalZADD([]string{"key", "5", "member1", "15", "member2", "25", "member3"}, store)

b.ResetTimer()
Expand Down
2 changes: 1 addition & 1 deletion internal/eval/hmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestHashMapIncrementValue(t *testing.T) {
}

func TestGetValueFromHashMap(t *testing.T) {
store := store.NewStore(nil, nil)
store := store.NewStore(nil, nil, nil)
key := "key1"
field := "field1"
value := "value1"
Expand Down
2 changes: 1 addition & 1 deletion internal/eval/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func TestMain(m *testing.M) {
store := dstore.NewStore(nil, nil)
store := dstore.NewStore(nil, nil, nil)
store.ResetStore()

exitCode := m.Run()
Expand Down
2 changes: 1 addition & 1 deletion internal/eval/store_eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ func evalAPPEND(args []string, store *dstore.Store) *EvalResponse {
if _, ok := obj.Value.(*sortedset.Set); ok {
return &EvalResponse{
Result: nil,
Error: diceerrors.ErrWrongTypeOperation,
Error: diceerrors.ErrWrongTypeOperation,
}
}
_, currentEnc := object.ExtractTypeEncoding(obj)
Expand Down
4 changes: 4 additions & 0 deletions internal/server/utils/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func (mc *MockClock) SetTime(t time.Time) {
mc.CurrTime = t
}

func (mc *MockClock) GetTime() time.Time {
return mc.CurrTime
}

func GetCurrentTime() time.Time {
return CurrentTime.Now()
}
Expand Down
Loading

0 comments on commit 2854dab

Please sign in to comment.