完成基础的hashmap

This commit is contained in:
eson 2019-04-23 03:05:25 +08:00
parent dd6309456f
commit 0f294d582d
3 changed files with 61 additions and 111 deletions

View File

@ -38,7 +38,7 @@ func New(hcode HashCode, comp compare.Compare) *HashMap {
} }
func (hm *HashMap) countNextGrow() { func (hm *HashMap) countNextGrow() {
hm.growsize = hm.table.Cap() << 2 hm.growsize = hm.table.Cap() << 1
} }
func (hm *HashMap) grow() { func (hm *HashMap) grow() {
@ -62,10 +62,10 @@ func (hm *HashMap) grow() {
var hash, index uint var hash, index uint
for _, node := range nodelist { for _, node := range nodelist {
hash = hm.GetHash(node.key) hash = hm.GetHash(node.key)
index = hash % newsize index = hash % hm.table.cap
//bkt := newtable[index] //bkt := newtable[index]
bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) { bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
(*xdata)[xindex] = avlNew(hm.Compare) data[idx] = avlNew(hm.Compare)
}) })
bkt.PutNode(node) bkt.PutNode(node)
} }
@ -80,10 +80,9 @@ func (hm *HashMap) Put(key, value interface{}) {
tlen := hm.table.Cap() tlen := hm.table.Cap()
index := hash % tlen index := hash % tlen
bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) { bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
(*xdata)[xindex] = avlNew(hm.Compare) data[idx] = avlNew(hm.Compare)
}) })
if bkt.Put(key, value) { if bkt.Put(key, value) {
hm.size++ hm.size++
hm.grow() hm.grow()

View File

@ -1,17 +1,33 @@
package hashmap package hashmap
import ( import (
"bytes"
"encoding/gob"
"fmt" "fmt"
"io/ioutil"
"log"
"runtime" "runtime"
"testing" "testing"
"474420502.top/eson/structure/compare" "474420502.top/eson/structure/compare"
) )
func loadTestData() []int {
log.SetFlags(log.Lshortfile)
data, err := ioutil.ReadFile("../l.log")
if err != nil {
log.Println(err)
}
var l []int
decoder := gob.NewDecoder(bytes.NewReader(data))
decoder.Decode(&l)
return l
}
func TestCount(t *testing.T) { func TestCount(t *testing.T) {
hm := New(HashInt, compare.Int) hm := New(HashInt, compare.Int)
for i := 0; i < 10; i++ { for i := 0; i < 100000; i++ {
hm.Put(i, i) hm.Put(i, i)
} }
@ -32,17 +48,42 @@ func bToMb(b uint64) uint64 {
return b / 1024 / 1024 return b / 1024 / 1024
} }
var executeCount = 5
var compareSize = 100000
func BenchmarkPut(b *testing.B) { func BenchmarkPut(b *testing.B) {
l := loadTestData()
hm := New(HashInt, compare.Int) hm := New(HashInt, compare.Int)
b.N = 100000 b.N = len(l) * executeCount
for i := 0; i < b.N; i++ { for c := 0; c < executeCount; c++ {
hm.Put(i, i) for i := 0; i < len(l); i++ {
v := l[i]
hm.Put(v, v)
}
} }
//b.Log(len(hm.table), hm.size) //b.Log(len(hm.table), hm.size)
//PrintMemUsage() //PrintMemUsage()
} }
func BenchmarkGoPut(b *testing.B) {
l := loadTestData()
hm := make(map[int]int)
b.N = len(l) * executeCount
for c := 0; c < executeCount; c++ {
for i := 0; i < len(l); i++ {
v := l[i]
hm[v] = v
}
}
//b.Log(len(m))
//PrintMemUsage()
}
func BenchmarkGet(b *testing.B) { func BenchmarkGet(b *testing.B) {
b.StopTimer() b.StopTimer()
hm := New(HashInt, compare.Int) hm := New(HashInt, compare.Int)
@ -59,16 +100,6 @@ func BenchmarkGet(b *testing.B) {
//PrintMemUsage() //PrintMemUsage()
} }
func BenchmarkGoPut(b *testing.B) {
m := make(map[int]int)
b.N = 100000
for i := 0; i < b.N; i++ {
m[i] = i
}
//b.Log(len(m))
//PrintMemUsage()
}
func BenchmarkGoGet(b *testing.B) { func BenchmarkGoGet(b *testing.B) {
b.StopTimer() b.StopTimer()
m := make(map[int]int) m := make(map[int]int)
@ -76,11 +107,6 @@ func BenchmarkGoGet(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m[i] = i m[i] = i
} }
for i := 0; i < b.N; i++ {
if _, ok := m[i]; !ok {
}
}
b.StartTimer() b.StartTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if _, ok := m[i]; !ok { if _, ok := m[i]; !ok {

View File

@ -8,124 +8,49 @@ type Table struct {
size uint size uint
growsize uint growsize uint
data [][4][4]*avlTree data []*avlTree
cap uint cap uint
} }
func newTable() *Table { func newTable() *Table {
table := &Table{} table := &Table{}
table.data = make([][4][4]*avlTree, 4, 4) table.data = make([]*avlTree, 16, 16)
table.countCap() table.countCap()
return table return table
} }
func (t *Table) countCap() { func (t *Table) countCap() {
t.cap = uint(len(t.data)) << 4 // * (4 * 4) t.cap = uint(len(t.data)) // * (4 * 4)
} }
// func (t *Table) countNextGrow() {
// t.growsize = uint(len(t.data)) << 6 // +4 * (4 * 4)
// }
// func (arr *Table) debugValues() []interface{} {
// var result []interface{}
// for _, z := range arr.data {
// if z != nil {
// for _, y := range z {
// if y == nil {
// for i := 0; i < arr.xsize; i++ {
// result = append(result, nil)
// }
// } else {
// for _, x := range y {
// if x == nil {
// result = append(result, struct{}{})
// } else {
// result = append(result, x)
// }
// }
// }
// }
// } else {
// for i := 0; i < arr.ysize*arr.xsize; i++ {
// result = append(result, nil)
// }
// }
// }
// return result
// }
// func (arr *Table) Values() []interface{} {
// var result []interface{}
// for _, z := range arr.data {
// if z != nil {
// for _, y := range z {
// if y == nil {
// for i := 0; i < arr.xsize; i++ {
// result = append(result, nil)
// }
// } else {
// for _, x := range y {
// if x == nil {
// result = append(result, nil)
// } else {
// result = append(result, x)
// }
// }
// }
// }
// } else {
// for i := 0; i < arr.ysize*arr.xsize; i++ {
// result = append(result, nil)
// }
// }
// }
// return result
// }
func (t *Table) Cap() uint { func (t *Table) Cap() uint {
return t.cap return t.cap
} }
func (t *Table) Traversal(every func(node *avlTree)) { func (t *Table) Traversal(every func(node *avlTree)) {
for _, z := range t.data { for _, z := range t.data {
for _, y := range z { every(z)
for _, x := range y {
every(x)
}
}
} }
} }
func (t *Table) Grow(size int) { func (t *Table) Grow(size int) {
zsize := len(t.data) + size zsize := len(t.data) + size
temp := make([][4][4]*avlTree, zsize, zsize) temp := make([]*avlTree, zsize, zsize)
copy(temp, t.data) copy(temp, t.data)
t.data = temp t.data = temp
t.countCap() t.countCap()
} }
func (t *Table) Get(idx uint) *avlTree { func (t *Table) Get(idx uint) *avlTree {
zindex := idx / 16 return t.data[idx]
nidx := (idx % 16)
yindex := nidx / 4
xindex := nidx % 4
return t.data[zindex][yindex][xindex]
} }
func (t *Table) GetWithNilSet(idx uint, DoSetValue func(*[4]*avlTree, uint)) *avlTree { func (t *Table) GetWithNilSet(idx uint, DoSetValue func([]*avlTree, uint)) *avlTree {
zindex := idx / 16
nidx := (idx % 16)
yindex := nidx / 4
xindex := nidx % 4
xdata := t.data[zindex][yindex] if t.data[idx] == nil {
if xdata[xindex] == nil { DoSetValue(t.data, idx)
DoSetValue(&xdata, xindex)
} }
return xdata[xindex] return t.data[idx]
} }
// func (arr *Table) Get(idx int) (interface{}, bool) { // func (arr *Table) Get(idx int) (interface{}, bool) {