@@ -5,20 +5,29 @@ import (
5
5
"encoding/binary"
6
6
"github.com/cockroachdb/swiss"
7
7
"github.com/xgzlucario/rotom/internal/iface"
8
+ "github.com/xgzlucario/rotom/internal/pool"
8
9
"github.com/xgzlucario/rotom/internal/resp"
9
10
)
10
11
12
+ const (
13
+ migrateThresholdRate = 0.5
14
+ migrateThresholdSize = 1024
15
+ )
16
+
11
17
var _ iface.MapI = (* ZipMap )(nil )
12
18
19
+ var (
20
+ bpool = pool .NewBufferPool ()
21
+ )
22
+
13
23
type ZipMap struct {
14
- unused uint32
24
+ unused int
15
25
data []byte
16
26
index * swiss.Map [string , uint32 ]
17
27
}
18
28
19
29
func New () * ZipMap {
20
30
return & ZipMap {
21
- data : make ([]byte , 0 , 64 ),
22
31
index : swiss.New [string , uint32 ](8 ),
23
32
}
24
33
}
@@ -34,22 +43,27 @@ func (zm *ZipMap) Get(key string) ([]byte, bool) {
34
43
35
44
func (zm * ZipMap ) Set (key string , val []byte ) bool {
36
45
pos , ok := zm .index .Get (key )
37
- // update inplace
46
+ // update inplaced
38
47
if ok {
39
48
oldVal , n := zm .readVal (pos )
40
49
if len (oldVal ) == len (val ) {
41
50
copy (oldVal , val )
42
51
return false
43
52
}
44
53
// mem trash
45
- zm .unused += uint32 (n )
54
+ zm .unused += n
55
+ zm .Migrate ()
46
56
}
47
- zm .index .Put (key , uint32 (len (zm .data )))
48
- zm .data = binary .AppendUvarint (zm .data , uint64 (len (val )))
49
- zm .data = append (zm .data , val ... )
57
+ zm .data = zm .appendKeyVal (zm .data , key , val )
50
58
return ! ok
51
59
}
52
60
61
+ func (zm * ZipMap ) appendKeyVal (dst []byte , key string , val []byte ) []byte {
62
+ zm .index .Put (key , uint32 (len (dst )))
63
+ dst = binary .AppendUvarint (dst , uint64 (len (val )))
64
+ return append (dst , val ... )
65
+ }
66
+
53
67
func (zm * ZipMap ) readVal (pos uint32 ) ([]byte , int ) {
54
68
data := zm .data [pos :]
55
69
vlen , n := binary .Uvarint (data )
@@ -62,7 +76,9 @@ func (zm *ZipMap) Remove(key string) bool {
62
76
if ok {
63
77
zm .index .Delete (key )
64
78
_ , n := zm .readVal (pos )
65
- zm .unused += uint32 (n )
79
+ // mem trash
80
+ zm .unused += n
81
+ zm .Migrate ()
66
82
}
67
83
return ok
68
84
}
@@ -75,13 +91,23 @@ func (zm *ZipMap) Scan(fn func(string, []byte)) {
75
91
})
76
92
}
77
93
78
- func (zm * ZipMap ) Len () int {
79
- return zm .index .Len ()
94
+ func (zm * ZipMap ) Migrate () {
95
+ if zm .unused < migrateThresholdSize {
96
+ return
97
+ }
98
+ if float64 (zm .unused )/ float64 (len (zm .data )) < migrateThresholdRate {
99
+ return
100
+ }
101
+ newData := bpool .Get (len (zm .data ))
102
+ zm .Scan (func (key string , val []byte ) {
103
+ newData = zm .appendKeyVal (newData , key , val )
104
+ })
105
+ bpool .Put (zm .data )
106
+ zm .data = newData
107
+ zm .unused = 0
80
108
}
81
109
82
- func (zm * ZipMap ) Compress () {
83
-
84
- }
110
+ func (zm * ZipMap ) Len () int { return zm .index .Len () }
85
111
86
112
func (zm * ZipMap ) Encode (writer * resp.Writer ) error {
87
113
writer .WriteArrayHead (zm .Len ())
0 commit comments