Skip to content

Commit

Permalink
feat: optimize hash struct
Browse files Browse the repository at this point in the history
  • Loading branch information
xgzlucario committed Nov 23, 2024
1 parent 7d4bc39 commit 7814efd
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 214 deletions.
10 changes: 2 additions & 8 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ func evalCommand(writer *resp.Writer, args []resp.RESP) {
}

func fetchMap(key []byte, setnx ...bool) (Map, error) {
return fetch(key, func() Map { return hash.NewZipMap() }, setnx...)
return fetch(key, func() Map { return hash.New() }, setnx...)
}

func fetchList(key []byte, setnx ...bool) (List, error) {
Expand All @@ -663,10 +663,6 @@ func fetch[T any](key []byte, new func() T, setnx ...bool) (T, error) {
// conversion zipped structure
if len(setnx) > 0 && setnx[0] {
switch data := object.(type) {
case *hash.ZipMap:
if data.Len() >= 256 {
db.dict.Set(string(key), data.ToMap())
}
case *hash.ZipSet:
if data.Len() >= 512 {
db.dict.Set(string(key), data.ToSet())
Expand Down Expand Up @@ -696,10 +692,8 @@ func getObjectType(object any) ObjectType {
return TypeString
case int:
return TypeInteger
case *hash.Map:
return TypeMap
case *hash.ZipMap:
return TypeZipMap
return TypeMap
case *hash.Set:
return TypeSet
case *hash.ZipSet:
Expand Down
4 changes: 1 addition & 3 deletions const.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const (
TypeString
TypeInteger
TypeMap
TypeZipMap
TypeSet
TypeZipSet
TypeList
Expand All @@ -36,8 +35,7 @@ const (

// type2c is objectType to new encoder.
var type2c = map[ObjectType]func() iface.Encoder{
TypeMap: func() iface.Encoder { return hash.NewMap() },
TypeZipMap: func() iface.Encoder { return hash.NewZipMap() },
TypeMap: func() iface.Encoder { return hash.New() },
TypeSet: func() iface.Encoder { return hash.NewSet() },
TypeZipSet: func() iface.Encoder { return hash.NewZipSet() },
TypeList: func() iface.Encoder { return list.New() },
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/zeebo/xxh3 v1.0.2 // indirect
golang.org/x/arch v0.12.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
github.com/zyedidia/generic v1.2.1 h1:Zv5KS/N2m0XZZiuLS82qheRG4X1o5gsWreGb0hR7XDc=
github.com/zyedidia/generic v1.2.1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis=
golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
Expand Down
33 changes: 17 additions & 16 deletions internal/benchmark/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,55 +23,57 @@ func gcPause() time.Duration {
}

func genKV(id int) (string, []byte) {
k := fmt.Sprintf("%08x", id)
k := fmt.Sprintf("key-%010d", id)
return k, []byte(k)
}

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

func main() {
c := ""
flag.StringVar(&c, "obj", "hashmap", "object to bench.")
n := 0
flag.StringVar(&c, "obj", "hashmap", "")
flag.IntVar(&n, "n", 512, "")
flag.Parse()
fmt.Println(c)

start := time.Now()
m := map[int]any{}

switch c {
case "hashmap":
case "stdmap":
for i := 0; i < 10000; i++ {
hm := hash.NewMap()
for i := 0; i < 512; i++ {
k, v := genKV(i)
hm.Set(k, v)
hm := map[string][]byte{}
for j := 0; j < n; j++ {
k, v := genKV(j)
hm[k] = v
}
m[i] = hm
}
case "zipmap":
for i := 0; i < 10000; i++ {
hm := hash.NewZipMap()
for i := 0; i < 512; i++ {
k, v := genKV(i)
hm := hash.New()
for j := 0; j < n; j++ {
k, v := genKV(j)
hm.Set(k, v)
}
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))
for j := 0; j < n; j++ {
zs.Set(genK(j), float64(j))
}
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))
for j := 0; j < n; j++ {
zs.Set(genK(j), float64(j))
}
m[i] = zs
}
Expand All @@ -84,7 +86,6 @@ func main() {
runtime.ReadMemStats(&mem)
debug.ReadGCStats(&stat)

fmt.Println("gcsys:", mem.GCSys/1024/1024, "mb")
fmt.Println("heap inuse:", mem.HeapInuse/1024/1024, "mb")
fmt.Println("heap object:", mem.HeapObjects/1024, "k")
fmt.Println("gc:", stat.NumGC)
Expand Down
3 changes: 1 addition & 2 deletions internal/hash/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import (
const N = 512

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

func BenchmarkSet(b *testing.B) {
Expand Down
30 changes: 6 additions & 24 deletions internal/hash/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ const MAX = 10000

func FuzzTestMap(f *testing.F) {
stdmap := make(map[string][]byte, MAX)
hashmap := NewMap()
zipmap := NewZipMap()
zipmap := New()

f.Fuzz(func(t *testing.T, op int, key, val string) {
ast := assert.New(t)
Expand All @@ -24,59 +23,42 @@ func FuzzTestMap(f *testing.F) {
}
_, ok := stdmap[key]
stdmap[key] = []byte(val)
ast.Equal(!ok, hashmap.Set(key, []byte(val)))
ast.Equal(!ok, zipmap.Set(key, []byte(val)))

case 3, 4, 5: // Get
val1, ok1 := stdmap[key]
val2, ok2 := hashmap.Get(key)
val3, ok3 := zipmap.Get(key)
val2, ok2 := zipmap.Get(key)

ast.Equal(string(val1), string(val2))
ast.Equal(string(val1), string(val3))
ast.Equal(ok1, ok2)
ast.Equal(ok1, ok3)

case 6, 7: // Delete
_, ok := stdmap[key]
delete(stdmap, key)
ast.Equal(ok, hashmap.Remove(key))
ast.Equal(ok, zipmap.Remove(key))

case 8: // Scan
n := len(stdmap)
kv1 := make([]string, 0, n)
kv2 := make([]string, 0, n)
kv3 := make([]string, 0, n)
for k, v := range stdmap {
kv1 = append(kv1, fmt.Sprintf("%s->%s", k, v))
}
hashmap.Scan(func(k string, v []byte) {
zipmap.Scan(func(k string, v []byte) {
kv2 = append(kv2, fmt.Sprintf("%s->%s", k, v))
})
// toMap
newMap := zipmap.ToMap()
newMap.Scan(func(k string, v []byte) {
kv3 = append(kv3, fmt.Sprintf("%s->%s", k, v))
})
ast.ElementsMatch(kv1, kv2)
ast.ElementsMatch(kv1, kv3)
ast.ElementsMatch(kv1, kv2)

case 9: // Encode
w := resp.NewWriter(0)

ast.Nil(hashmap.Encode(w))
hashmap = NewMap()
ast.Nil(hashmap.Decode(resp.NewReader(w.Bytes())))

w.Reset()
ast.Nil(zipmap.Encode(w))
zipmap = NewZipMap()
zipmap = New()
ast.Nil(zipmap.Decode(resp.NewReader(w.Bytes())))

n := len(stdmap)
ast.Equal(n, hashmap.Len())
ast.Equal(n, zipmap.Len())
ast.Equal(len(stdmap), zipmap.Len())
}
})
}
Expand Down
76 changes: 0 additions & 76 deletions internal/hash/map.go

This file was deleted.

Loading

0 comments on commit 7814efd

Please sign in to comment.