Skip to content

Commit

Permalink
feat: zipmap support migrate
Browse files Browse the repository at this point in the history
  • Loading branch information
xgzlucario committed Nov 24, 2024
1 parent 7814efd commit 53d3195
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 14 deletions.
4 changes: 3 additions & 1 deletion internal/benchmark/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func main() {
flag.StringVar(&c, "obj", "hashmap", "")
flag.IntVar(&n, "n", 512, "")
flag.Parse()
fmt.Println(c)
fmt.Println(c, n)

start := time.Now()
m := map[int]any{}
Expand Down Expand Up @@ -77,6 +77,8 @@ func main() {
}
m[i] = zs
}
default:
panic("unknown flags")
}

cost := time.Since(start)
Expand Down
52 changes: 39 additions & 13 deletions internal/hash/zipmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,29 @@ import (
"encoding/binary"
"github.com/cockroachdb/swiss"
"github.com/xgzlucario/rotom/internal/iface"
"github.com/xgzlucario/rotom/internal/pool"
"github.com/xgzlucario/rotom/internal/resp"
)

const (
migrateThresholdRate = 0.5
migrateThresholdSize = 1024
)

var _ iface.MapI = (*ZipMap)(nil)

var (
bpool = pool.NewBufferPool()
)

type ZipMap struct {
unused uint32
unused int
data []byte
index *swiss.Map[string, uint32]
}

func New() *ZipMap {
return &ZipMap{
data: make([]byte, 0, 64),
index: swiss.New[string, uint32](8),
}
}
Expand All @@ -34,22 +43,27 @@ func (zm *ZipMap) Get(key string) ([]byte, bool) {

func (zm *ZipMap) Set(key string, val []byte) bool {
pos, ok := zm.index.Get(key)
// update inplace
// update inplaced
if ok {
oldVal, n := zm.readVal(pos)
if len(oldVal) == len(val) {
copy(oldVal, val)
return false
}
// mem trash
zm.unused += uint32(n)
zm.unused += n
zm.Migrate()
}
zm.index.Put(key, uint32(len(zm.data)))
zm.data = binary.AppendUvarint(zm.data, uint64(len(val)))
zm.data = append(zm.data, val...)
zm.data = zm.appendKeyVal(zm.data, key, val)
return !ok
}

func (zm *ZipMap) appendKeyVal(dst []byte, key string, val []byte) []byte {
zm.index.Put(key, uint32(len(dst)))
dst = binary.AppendUvarint(dst, uint64(len(val)))
return append(dst, val...)
}

func (zm *ZipMap) readVal(pos uint32) ([]byte, int) {
data := zm.data[pos:]
vlen, n := binary.Uvarint(data)
Expand All @@ -62,7 +76,9 @@ func (zm *ZipMap) Remove(key string) bool {
if ok {
zm.index.Delete(key)
_, n := zm.readVal(pos)
zm.unused += uint32(n)
// mem trash
zm.unused += n
zm.Migrate()
}
return ok
}
Expand All @@ -75,13 +91,23 @@ func (zm *ZipMap) Scan(fn func(string, []byte)) {
})
}

func (zm *ZipMap) Len() int {
return zm.index.Len()
func (zm *ZipMap) Migrate() {
if zm.unused < migrateThresholdSize {
return
}
if float64(zm.unused)/float64(len(zm.data)) < migrateThresholdRate {
return
}
newData := bpool.Get(len(zm.data))
zm.Scan(func(key string, val []byte) {
newData = zm.appendKeyVal(newData, key, val)
})
bpool.Put(zm.data)
zm.data = newData
zm.unused = 0
}

func (zm *ZipMap) Compress() {

}
func (zm *ZipMap) Len() int { return zm.index.Len() }

func (zm *ZipMap) Encode(writer *resp.Writer) error {
writer.WriteArrayHead(zm.Len())
Expand Down

0 comments on commit 53d3195

Please sign in to comment.