diff --git a/hashmap/hashmap.go b/hashmap/hashmap.go index 317ccec..fccb44d 100644 --- a/hashmap/hashmap.go +++ b/hashmap/hashmap.go @@ -38,7 +38,7 @@ func New(hcode HashCode, comp compare.Compare) *HashMap { } func (hm *HashMap) countNextGrow() { - hm.growsize = hm.table.Cap() << 2 + hm.growsize = hm.table.Cap() << 1 } func (hm *HashMap) grow() { @@ -62,10 +62,10 @@ func (hm *HashMap) grow() { var hash, index uint for _, node := range nodelist { hash = hm.GetHash(node.key) - index = hash % newsize + index = hash % hm.table.cap //bkt := newtable[index] - bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) { - (*xdata)[xindex] = avlNew(hm.Compare) + bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) { + data[idx] = avlNew(hm.Compare) }) bkt.PutNode(node) } @@ -80,10 +80,9 @@ func (hm *HashMap) Put(key, value interface{}) { tlen := hm.table.Cap() index := hash % tlen - bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) { - (*xdata)[xindex] = avlNew(hm.Compare) + bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) { + data[idx] = avlNew(hm.Compare) }) - if bkt.Put(key, value) { hm.size++ hm.grow() diff --git a/hashmap/hashmap_test.go b/hashmap/hashmap_test.go index 53b7291..14a7318 100644 --- a/hashmap/hashmap_test.go +++ b/hashmap/hashmap_test.go @@ -1,17 +1,33 @@ package hashmap import ( + "bytes" + "encoding/gob" "fmt" + "io/ioutil" + "log" "runtime" "testing" "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) { hm := New(HashInt, compare.Int) - for i := 0; i < 10; i++ { + for i := 0; i < 100000; i++ { hm.Put(i, i) } @@ -32,17 +48,42 @@ func bToMb(b uint64) uint64 { return b / 1024 / 1024 } +var executeCount = 5 +var compareSize = 100000 + func BenchmarkPut(b *testing.B) { + l := loadTestData() + hm := New(HashInt, compare.Int) - b.N = 100000 - for i := 0; i < b.N; i++ { - hm.Put(i, i) + b.N = len(l) * executeCount + for c := 0; c < executeCount; c++ { + for i := 0; i < len(l); i++ { + v := l[i] + hm.Put(v, v) + } } //b.Log(len(hm.table), hm.size) //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) { b.StopTimer() hm := New(HashInt, compare.Int) @@ -59,16 +100,6 @@ func BenchmarkGet(b *testing.B) { //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) { b.StopTimer() m := make(map[int]int) @@ -76,11 +107,6 @@ func BenchmarkGoGet(b *testing.B) { for i := 0; i < b.N; i++ { m[i] = i } - for i := 0; i < b.N; i++ { - if _, ok := m[i]; !ok { - - } - } b.StartTimer() for i := 0; i < b.N; i++ { if _, ok := m[i]; !ok { diff --git a/hashmap/table.go b/hashmap/table.go index 9b04370..3944ca2 100644 --- a/hashmap/table.go +++ b/hashmap/table.go @@ -8,124 +8,49 @@ type Table struct { size uint growsize uint - data [][4][4]*avlTree + data []*avlTree cap uint } func newTable() *Table { table := &Table{} - table.data = make([][4][4]*avlTree, 4, 4) + table.data = make([]*avlTree, 16, 16) table.countCap() return table } 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 { return t.cap } func (t *Table) Traversal(every func(node *avlTree)) { for _, z := range t.data { - for _, y := range z { - for _, x := range y { - every(x) - } - } + every(z) } } func (t *Table) Grow(size int) { zsize := len(t.data) + size - temp := make([][4][4]*avlTree, zsize, zsize) + temp := make([]*avlTree, zsize, zsize) copy(temp, t.data) t.data = temp t.countCap() } func (t *Table) Get(idx uint) *avlTree { - zindex := idx / 16 - nidx := (idx % 16) - yindex := nidx / 4 - xindex := nidx % 4 - return t.data[zindex][yindex][xindex] + return t.data[idx] } -func (t *Table) GetWithNilSet(idx uint, DoSetValue func(*[4]*avlTree, uint)) *avlTree { - zindex := idx / 16 - nidx := (idx % 16) - yindex := nidx / 4 - xindex := nidx % 4 +func (t *Table) GetWithNilSet(idx uint, DoSetValue func([]*avlTree, uint)) *avlTree { - xdata := t.data[zindex][yindex] - if xdata[xindex] == nil { - DoSetValue(&xdata, xindex) + if t.data[idx] == nil { + DoSetValue(t.data, idx) } - return xdata[xindex] + return t.data[idx] } // func (arr *Table) Get(idx int) (interface{}, bool) {