Skip to content

Commit

Permalink
feat: add zipzset
Browse files Browse the repository at this point in the history
  • Loading branch information
xgzlucario committed Nov 16, 2024
1 parent ca20be8 commit cbf3df7
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 119 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ run-gc:

test-cover:
make clean
go test . -race -coverprofile=coverage.txt -covermode=atomic
go test ./... -race -coverprofile=coverage.txt -covermode=atomic
go tool cover -html=coverage.txt -o coverage.html

fuzz-test:
Expand Down
24 changes: 22 additions & 2 deletions internal/hash/benchmark/main.go → internal/benchmark/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"flag"
"fmt"
"github.com/xgzlucario/rotom/internal/zset"
"runtime"
"runtime/debug"
"time"
Expand All @@ -26,6 +27,10 @@ func genKV(id int) (string, []byte) {
return k, []byte(k)
}

func genK(id int) string {
return fmt.Sprintf("%08x", id)
}

func main() {
c := ""
flag.StringVar(&c, "obj", "hashmap", "object to bench.")
Expand All @@ -45,7 +50,6 @@ func main() {
}
m[i] = hm
}

case "zipmap":
for i := 0; i < 10000; i++ {
hm := hash.NewZipMap()
Expand All @@ -55,9 +59,25 @@ func main() {
}
m[i] = hm
}
case "zset":
for i := 0; i < 10000; i++ {
zs := zset.New()
for i := 0; i < 512; i++ {
zs.Set(genK(i), float64(i))
}
m[i] = zs
}
case "zipzset":
for i := 0; i < 10000; i++ {
zs := zset.NewZipZSet()
for i := 0; i < 512; i++ {
zs.Set(genK(i), float64(i))
}
m[i] = zs
}
}
cost := time.Since(start)

cost := time.Since(start)
var mem runtime.MemStats
var stat debug.GCStats

Expand Down
17 changes: 9 additions & 8 deletions internal/hash/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,42 @@ package hash

import (
"fmt"
"github.com/xgzlucario/rotom/internal/iface"
"testing"
)

const N = 512

func BenchmarkMap(b *testing.B) {
benchMapI("map", func() MapI { return NewMap() }, b)
benchMapI("zipmap", func() MapI { return NewZipMap() }, b)
benchMapI("map", func() iface.MapI { return NewMap() }, b)
benchMapI("zipmap", func() iface.MapI { return NewZipMap() }, b)
}

func BenchmarkSet(b *testing.B) {
benchSetI("set", func() SetI { return NewSet() }, b)
benchSetI("zipset", func() SetI { return NewZipSet() }, b)
benchSetI("set", func() iface.SetI { return NewSet() }, b)
benchSetI("zipset", func() iface.SetI { return NewZipSet() }, b)
}

func genKey(i int) string {
return fmt.Sprintf("%08x", i)
}

func genMap(m MapI, n int) MapI {
func genMap(m iface.MapI, n int) iface.MapI {
for i := 0; i < n; i++ {
k := genKey(i)
m.Set(k, []byte(k))
}
return m
}

func genSet(s SetI, n int) SetI {
func genSet(s iface.SetI, n int) iface.SetI {
for i := 0; i < n; i++ {
s.Add(genKey(i))
}
return s
}

func benchMapI(name string, newf func() MapI, b *testing.B) {
func benchMapI(name string, newf func() iface.MapI, b *testing.B) {
b.Run(name+"/get", func(b *testing.B) {
m := genMap(newf(), N)
b.ResetTimer()
Expand Down Expand Up @@ -68,7 +69,7 @@ func benchMapI(name string, newf func() MapI, b *testing.B) {
})
}

func benchSetI(name string, newf func() SetI, b *testing.B) {
func benchSetI(name string, newf func() iface.SetI, b *testing.B) {
b.Run(name+"/add", func(b *testing.B) {
m := newf()
for i := 0; i < b.N; i++ {
Expand Down
11 changes: 1 addition & 10 deletions internal/hash/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,7 @@ import (
"github.com/xgzlucario/rotom/internal/resp"
)

type MapI interface {
iface.Encoder
Set(key string, val []byte) bool
Get(key string) ([]byte, bool)
Remove(key string) bool
Len() int
Scan(fn func(key string, val []byte))
}

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

type Map struct {
data *swiss.Map[string, []byte]
Expand Down
12 changes: 1 addition & 11 deletions internal/hash/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,7 @@ const (
defaultSetSize = 512
)

type SetI interface {
iface.Encoder
Add(key string) bool
Exist(key string) bool
Remove(key string) bool
Pop() (key string, ok bool)
Scan(fn func(key string))
Len() int
}

var _ SetI = (*Set)(nil)
var _ iface.SetI = (*Set)(nil)

type Set struct {
mapset.Set[string]
Expand Down
11 changes: 6 additions & 5 deletions internal/hash/zipmap.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package hash

import (
"github.com/xgzlucario/rotom/internal/iface"
"github.com/xgzlucario/rotom/internal/resp"
"unsafe"

"github.com/xgzlucario/rotom/internal/list"
)

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

// ZipMap store data as [val1, key1, val2, key2...] in listpack.
type ZipMap struct {
Expand All @@ -18,7 +19,7 @@ func NewZipMap() *ZipMap {
return &ZipMap{list.NewListPack()}
}

func (zm *ZipMap) seekTo(key string) (it *list.LpIterator, val []byte) {
func (zm *ZipMap) seek(key string) (it *list.LpIterator, val []byte) {
it = zm.data.Iterator().SeekLast()
for !it.IsFirst() {
kBytes := it.Prev()
Expand All @@ -31,7 +32,7 @@ func (zm *ZipMap) seekTo(key string) (it *list.LpIterator, val []byte) {
}

func (zm *ZipMap) Set(key string, val []byte) (newField bool) {
it, oldVal := zm.seekTo(key)
it, oldVal := zm.seek(key)
// update
if it != nil {
if len(val) == len(oldVal) {
Expand All @@ -47,15 +48,15 @@ func (zm *ZipMap) Set(key string, val []byte) (newField bool) {
}

func (zm *ZipMap) Get(key string) ([]byte, bool) {
_, val := zm.seekTo(key)
_, val := zm.seek(key)
if val != nil {
return val, true
}
return nil, false
}

func (zm *ZipMap) Remove(key string) bool {
it, _ := zm.seekTo(key)
it, _ := zm.seek(key)
if it != nil {
it.RemoveNexts(2, nil)
return true
Expand Down
3 changes: 2 additions & 1 deletion internal/hash/zipset.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package hash

import (
"github.com/xgzlucario/rotom/internal/iface"
"github.com/xgzlucario/rotom/internal/list"
"github.com/xgzlucario/rotom/internal/resp"
)

var _ SetI = (*ZipSet)(nil)
var _ iface.SetI = (*ZipSet)(nil)

// ZipSet store data as [key1, key2, key3...] in listpack.
type ZipSet struct {
Expand Down
8 changes: 0 additions & 8 deletions internal/iface/encoder.go

This file was deleted.

38 changes: 38 additions & 0 deletions internal/iface/iface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package iface

import "github.com/xgzlucario/rotom/internal/resp"

type Encoder interface {
Encode(writer *resp.Writer) error
Decode(reader *resp.Reader) error
}

type MapI interface {
Encoder
Set(key string, val []byte) bool
Get(key string) ([]byte, bool)
Remove(key string) bool
Len() int
Scan(fn func(key string, val []byte))
}

type SetI interface {
Encoder
Add(key string) bool
Exist(key string) bool
Remove(key string) bool
Pop() (key string, ok bool)
Scan(fn func(key string))
Len() int
}

type ListI interface {
Encoder
}

type ZSetI interface {
Encoder
Get(key string) (score float64, ok bool)
Set(key string, score float64) bool
Len() int
}
2 changes: 1 addition & 1 deletion net.go → internal/net/net.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package net

import (
"golang.org/x/sys/unix"
Expand Down
2 changes: 1 addition & 1 deletion net_test.go → internal/net/net_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package net

import (
"fmt"
Expand Down
63 changes: 0 additions & 63 deletions internal/zset/benchmark/main.go

This file was deleted.

Loading

0 comments on commit cbf3df7

Please sign in to comment.