Skip to content

Commit 3043e41

Browse files
committed
更新下cmap
1 parent e58f9b1 commit 3043e41

File tree

8 files changed

+141
-34
lines changed

8 files changed

+141
-34
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
# Output of the go coverage tool, specifically when used with LiteIDE
1212
*.out
13+
*.log
1314

1415
# Dependency directories (remove the comment below to include it)
1516
# vendor/

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
```
1414

1515
## 三、`rhashmap`
16-
和标准库不同的地址是有序hash
16+
和标准库不同的地方是有序hash
1717
```go
1818
```
1919

btree/btree_bench_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ func BenchmarkGetStd(b *testing.B) {
6363

6464
max := float64(b.N)
6565
//max := 1000000.0 * 5
66-
set := make(map[float64]float64, int(max))
66+
set := make(map[float64]float64)
67+
//set := make(map[float64]float64, int(max))
6768
for i := 0.0; i < max; i++ {
6869
set[i] = i
6970
}

cmap/cmap.go

+30-27
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,29 @@ import (
77
"unsafe"
88

99
"github.com/antlabs/gstl/api"
10-
"github.com/antlabs/gstl/mapex"
1110
xxhash "github.com/cespare/xxhash/v2"
11+
"golang.org/x/exp/constraints"
1212
)
1313

1414
var _ api.CMaper[int, int] = (*CMap[int, int])(nil)
1515

16-
type Pair[K comparable, V any] struct {
16+
type Pair[K constraints.Ordered, V any] struct {
1717
Key K
1818
Val V
1919
}
2020

21-
type CMap[K comparable, V any] struct {
21+
type CMap[K constraints.Ordered, V any] struct {
2222
bucket []Item[K, V]
2323
keySize int
2424
isKeyStr bool
2525
}
2626

27-
type Item[K comparable, V any] struct {
27+
type Item[K constraints.Ordered, V any] struct {
2828
rw sync.RWMutex
29-
m map[K]V
29+
m api.Map[K, V]
3030
}
3131

32-
func New[K comparable, V any]() (c *CMap[K, V]) {
32+
func New[K constraints.Ordered, V any]() (c *CMap[K, V]) {
3333
c = &CMap[K, V]{}
3434
c.init(0)
3535
return c
@@ -48,7 +48,7 @@ func (c *CMap[K, V]) init(n int) {
4848
c.bucket = make([]Item[K, V], np)
4949

5050
for i := range c.bucket {
51-
c.bucket[i].m = make(map[K]V)
51+
c.bucket[i].m = newStdMap[K, V]()
5252
}
5353

5454
}
@@ -92,42 +92,43 @@ func (c *CMap[K, V]) findIndex(key K) *Item[K, V] {
9292
func (c *CMap[K, V]) Delete(key K) {
9393
item := c.findIndex(key)
9494
item.rw.Lock()
95-
delete(item.m, key)
95+
item.m.Delete(key)
9696
item.rw.Unlock()
9797
}
9898

9999
func (c *CMap[K, V]) Load(key K) (value V, ok bool) {
100100
item := c.findIndex(key)
101101
item.rw.RLock()
102-
value, ok = item.m[key]
102+
value, ok = item.m.GetWithBool(key)
103103
item.rw.RUnlock()
104104
return
105105
}
106106

107107
func (c *CMap[K, V]) LoadAndDelete(key K) (value V, loaded bool) {
108108
item := c.findIndex(key)
109109
item.rw.Lock()
110-
value, loaded = item.m[key]
110+
value, loaded = item.m.GetWithBool(key)
111111
if !loaded {
112112
item.rw.Unlock()
113113
return
114114
}
115-
delete(item.m, key)
115+
item.m.Delete(key)
116116
item.rw.Unlock()
117117
return
118118
}
119119

120120
func (c *CMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
121121
item := c.findIndex(key)
122122
item.rw.Lock()
123-
actual, loaded = item.m[key]
123+
actual, loaded = item.m.GetWithBool(key)
124124
if !loaded {
125125
actual = value
126-
item.m[key] = actual
126+
item.m.Set(key, actual)
127127
item.rw.Unlock()
128128
return
129129
}
130-
actual, loaded = item.m[key]
130+
131+
actual, loaded = item.m.GetWithBool(key)
131132
item.rw.Unlock()
132133
return
133134
}
@@ -136,12 +137,7 @@ func (c *CMap[K, V]) Range(f func(key K, value V) bool) {
136137
for i := 0; i < len(c.bucket); i++ {
137138
item := &c.bucket[i]
138139
item.rw.RLock()
139-
for k, v := range item.m {
140-
if !f(k, v) {
141-
item.rw.RUnlock()
142-
return
143-
}
144-
}
140+
item.m.Range(f)
145141
item.rw.RUnlock()
146142
}
147143
}
@@ -164,9 +160,10 @@ func (c *CMap[K, V]) Iter() (rv chan Pair[K, V]) {
164160

165161
defer wg.Done()
166162
item.rw.RLock()
167-
for k, v := range item.m {
168-
rv <- Pair[K, V]{Key: k, Val: v}
169-
}
163+
item.m.Range(func(key K, value V) bool {
164+
rv <- Pair[K, V]{Key: key, Val: value}
165+
return true
166+
})
170167
item.rw.RUnlock()
171168

172169
}(item)
@@ -178,7 +175,7 @@ func (c *CMap[K, V]) Iter() (rv chan Pair[K, V]) {
178175
func (c *CMap[K, V]) Store(key K, value V) {
179176
item := c.findIndex(key)
180177
item.rw.Lock()
181-
item.m[key] = value
178+
item.m.Set(key, value)
182179
item.rw.Unlock()
183180
return
184181
}
@@ -195,7 +192,10 @@ func (c *CMap[K, V]) Keys() []K {
195192

196193
item := &c.bucket[i]
197194
item.rw.RLock()
198-
all = append(all, mapex.Keys(item.m)...)
195+
item.m.Range(func(key K, value V) bool {
196+
all = append(all, key)
197+
return true
198+
})
199199
item.rw.RUnlock()
200200
}
201201
return all
@@ -212,7 +212,10 @@ func (c *CMap[K, V]) Values() []V {
212212

213213
item := &c.bucket[i]
214214
item.rw.RLock()
215-
all = append(all, mapex.Values(item.m)...)
215+
item.m.Range(func(key K, value V) bool {
216+
all = append(all, value)
217+
return true
218+
})
216219
item.rw.RUnlock()
217220
}
218221
return all
@@ -223,7 +226,7 @@ func (c *CMap[K, V]) Len() int {
223226
for i := 0; i < len(c.bucket); i++ {
224227
item := &c.bucket[i]
225228
item.rw.RLock()
226-
l += len(item.m)
229+
l += item.m.Len()
227230
item.rw.RUnlock()
228231
}
229232
return l

cmap/cmap_bench_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func benchMap(b *testing.B, bench bench[int, int]) {
7272
b.Run(fmt.Sprintf("%T", m), func(b *testing.B) {
7373
m = reflect.New(reflect.TypeOf(m).Elem()).Interface().(api.CMaper[int, int])
7474
if m2, ok := m.(*CMap[int, int]); ok {
75-
m2.init(1)
75+
m2.init(64)
7676
}
7777

7878
if bench.setup != nil {

cmap/cmap_stdmap.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package cmap
2+
3+
import (
4+
"github.com/antlabs/gstl/api"
5+
"golang.org/x/exp/constraints"
6+
)
7+
8+
var _ api.Map[int, int] = (*stdmap[int, int])(nil)
9+
10+
type stdmap[K constraints.Ordered, V any] struct {
11+
m map[K]V
12+
}
13+
14+
func newStdMap[K constraints.Ordered, V any]() *stdmap[K, V] {
15+
return &stdmap[K, V]{m: make(map[K]V)}
16+
}
17+
18+
func (s *stdmap[K, V]) Get(key K) (elem V) {
19+
elem, _ = s.m[key]
20+
return
21+
}
22+
23+
// 获取
24+
func (s *stdmap[K, V]) GetWithBool(key K) (elem V, ok bool) {
25+
elem, ok = s.m[key]
26+
return
27+
}
28+
29+
// 删除
30+
func (s *stdmap[K, V]) Delete(key K) {
31+
delete(s.m, key)
32+
}
33+
34+
// 设置
35+
func (s *stdmap[K, V]) Set(key K, value V) {
36+
s.m[key] = value
37+
}
38+
39+
// 设置值
40+
func (s *stdmap[K, V]) SetWithPrev(key K, value V) (prev V, replaced bool) {
41+
prev, replaced = s.m[key]
42+
s.m[key] = value
43+
return
44+
}
45+
46+
// int
47+
func (s *stdmap[K, V]) Len() int {
48+
return len(s.m)
49+
}
50+
51+
// 遍历
52+
func (s *stdmap[K, V]) Range(callback func(k K, v V) bool) {
53+
for k, v := range s.m {
54+
if !callback(k, v) {
55+
return
56+
}
57+
}
58+
}

rbtree/rbtree_bench_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ import (
2929
"testing"
3030
)
3131

32+
func BenchmarkSetAsc(b *testing.B) {
33+
//max := 1000000.0 * 5
34+
set := New[float64, float64]()
35+
max := float64(b.N)
36+
for i := 0.0; i < max; i++ {
37+
set.Set(i, i)
38+
}
39+
40+
}
41+
3242
func BenchmarkGetAsc(b *testing.B) {
3343
//max := 1000000.0 * 5
3444
set := New[float64, float64]()
@@ -83,3 +93,23 @@ func BenchmarkGetStd(b *testing.B) {
8393
}
8494
}
8595
}
96+
97+
func BenchmarkSet(b *testing.B) {
98+
max := float64(b.N)
99+
//max := 1000000.0 * 5
100+
set := New[float64, float64]()
101+
for i := max; i >= 0; i-- {
102+
set.Set(i, i)
103+
}
104+
105+
}
106+
107+
func BenchmarkSetStd(b *testing.B) {
108+
max := float64(b.N)
109+
//max := 1000000.0 * 5
110+
set := make(map[float64]float64)
111+
for i := max; i >= 0.0; i-- {
112+
set[i] = i
113+
}
114+
115+
}

rhashmap/rhashmap_bench_test.go

+18-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,22 @@ import (
2525
// PASS
2626
// ok github.com/antlabs/gstl/rhashmap 3.970s
2727
// 五百万数据的Get操作时间
28+
29+
// TODO 再优化下性能
30+
// go1.19.1
31+
// 3kw
32+
// goos: darwin
33+
// goarch: arm64
34+
// pkg: github.com/antlabs/gstl/rhashmap
35+
// BenchmarkGet-8 34664005 62.20 ns/op
36+
// BenchmarkGetStd-8 30007470 49.40 ns/op
37+
// BenchmarkSet-8 14623854 178.9 ns/op
38+
// BenchmarkSetStd-8 22709601 74.71 ns/op
39+
// PASS
40+
// ok github.com/antlabs/gstl/rhashmap 16.521s
2841
func BenchmarkGet(b *testing.B) {
29-
max := 1000000.0 * 5
42+
//max := 1000000.0 * 5
43+
max := float64(b.N)
3044
set := NewWithOpt[float64, float64](WithCap(int(max)))
3145
for i := 0.0; i < max; i++ {
3246
set.Set(i, i)
@@ -44,7 +58,7 @@ func BenchmarkGet(b *testing.B) {
4458

4559
func BenchmarkGetStd(b *testing.B) {
4660

47-
max := 1000000.0 * 5
61+
max := float64(b.N)
4862
set := make(map[float64]float64, int(max))
4963
for i := 0.0; i < max; i++ {
5064
set[i] = i
@@ -62,7 +76,7 @@ func BenchmarkGetStd(b *testing.B) {
6276

6377
// gstl set
6478
func BenchmarkSet(b *testing.B) {
65-
max := 1000000.0
79+
max := float64(b.N)
6680
set := NewWithOpt[float64, float64](WithCap(int(max)))
6781
for i := 0.0; i < max; i++ {
6882
set.Set(i, i)
@@ -73,7 +87,7 @@ func BenchmarkSet(b *testing.B) {
7387
// 标准库set
7488
func BenchmarkSetStd(b *testing.B) {
7589

76-
max := 1000000.0
90+
max := float64(b.N)
7791
set := make(map[float64]float64, int(max))
7892
for i := 0.0; i < max; i++ {
7993
set[i] = i

0 commit comments

Comments
 (0)