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 13, 2024
1 parent d26d77a commit 0030a0c
Show file tree
Hide file tree
Showing 23 changed files with 502 additions and 437 deletions.
45 changes: 24 additions & 21 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 All @@ -50,7 +48,8 @@ var (

InitConfigCmd = false

KeysLimit = DefaultKeysLimit
KeysLimit = DefaultKeysLimit
EvictionRatio = DefaultEvictionRatio

EnableProfiling = false

Expand Down Expand Up @@ -97,11 +96,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 +180,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 Expand Up @@ -366,6 +365,10 @@ func mergeFlagsWithConfig() {
if KeysLimit != DefaultKeysLimit {
DiceConfig.Memory.KeysLimit = KeysLimit
}

if EvictionRatio != DefaultEvictionRatio {
DiceConfig.Memory.EvictionRatio = EvictionRatio
}
}

// This function checks if the config file is present or not at default location or at -c flag location
Expand Down
2 changes: 1 addition & 1 deletion dice.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ AdhocReqChanBufSize = 20
[Memory]
MaxMemory = 0
EvictionPolicy = 'allkeys-lfu'
EvictionRatio = 0.9
EvictionRatio = 0.1
KeysLimit = 200000000
LFULogFactor = 10

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 @@ -453,13 +453,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 @@ -1493,7 +1486,6 @@ func init() {
DiceCmds["LLEN"] = llenCmdMeta
DiceCmds["LPOP"] = lpopCmdMeta
DiceCmds["LPUSH"] = lpushCmdMeta
DiceCmds["LRU"] = lruCmdMeta
DiceCmds["MGET"] = MGetCmdMeta
DiceCmds["MSET"] = msetCmdMeta
DiceCmds["OBJECT"] = objectCmdMeta
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 @@ -576,13 +576,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 @@ -1572,7 +1570,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 @@ -4367,13 +4365,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 @@ -4666,7 +4664,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 @@ -4678,7 +4676,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 @@ -5025,7 +5023,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 @@ -5337,7 +5335,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 @@ -5681,7 +5679,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 @@ -5939,7 +5937,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 @@ -5964,7 +5962,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 @@ -6067,15 +6065,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 @@ -6327,7 +6325,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 @@ -6506,7 +6504,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 @@ -6745,7 +6743,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 @@ -7059,7 +7057,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 @@ -7787,7 +7785,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 @@ -7953,7 +7951,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 @@ -8235,7 +8233,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 @@ -8619,7 +8617,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 @@ -8743,7 +8741,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 @@ -8759,7 +8757,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 @@ -8788,7 +8786,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
Loading

0 comments on commit 0030a0c

Please sign in to comment.