Skip to content

Commit d509f27

Browse files
author
Ignacio Van Droogenbroeck
committed
perf(encode): pool sorted map key slices via sync.Pool
Replaces per-call make([]string, 0, len(m)) with a sync.Pool of reusable key slices in EncodeMapSorted, encodeSortedMapStringBool, and encodeSortedMapStringString. Eliminates 1 alloc per sorted map encode for callers using SetSortMapKeys(true).
1 parent 82f46cf commit d509f27

1 file changed

Lines changed: 55 additions & 9 deletions

File tree

encode_map.go

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,35 @@ import (
44
"math"
55
"reflect"
66
"sort"
7+
"sync"
78

89
"github.com/vmihailenco/msgpack/v5/msgpcode"
910
)
1011

12+
var sortedKeysPool = sync.Pool{
13+
New: func() interface{} {
14+
s := make([]string, 0, 16)
15+
return &s
16+
},
17+
}
18+
19+
func getSortedKeys(n int) *[]string {
20+
sp := sortedKeysPool.Get().(*[]string)
21+
if cap(*sp) < n {
22+
*sp = make([]string, 0, n)
23+
} else {
24+
*sp = (*sp)[:0]
25+
}
26+
return sp
27+
}
28+
29+
func putSortedKeys(sp *[]string) {
30+
if cap(*sp) > 1024 {
31+
return // don't retain oversized slices
32+
}
33+
sortedKeysPool.Put(sp)
34+
}
35+
1136
func encodeMapValue(e *Encoder, v reflect.Value) error {
1237
if v.IsNil() {
1338
return e.EncodeNil()
@@ -119,7 +144,8 @@ func (e *Encoder) EncodeMapSorted(m map[string]interface{}) error {
119144
return err
120145
}
121146

122-
keys := make([]string, 0, len(m))
147+
sp := getSortedKeys(len(m))
148+
keys := *sp
123149

124150
for k := range m {
125151
keys = append(keys, k)
@@ -129,53 +155,73 @@ func (e *Encoder) EncodeMapSorted(m map[string]interface{}) error {
129155

130156
for _, k := range keys {
131157
if err := e.EncodeString(k); err != nil {
158+
*sp = keys
159+
putSortedKeys(sp)
132160
return err
133161
}
134162
if err := e.Encode(m[k]); err != nil {
163+
*sp = keys
164+
putSortedKeys(sp)
135165
return err
136166
}
137167
}
138168

169+
*sp = keys
170+
putSortedKeys(sp)
139171
return nil
140172
}
141173

142174
func (e *Encoder) encodeSortedMapStringBool(m map[string]bool) error {
143-
keys := make([]string, 0, len(m))
175+
sp := getSortedKeys(len(m))
176+
keys := *sp
177+
144178
for k := range m {
145179
keys = append(keys, k)
146180
}
147181
sort.Strings(keys)
148182

149183
for _, k := range keys {
150-
err := e.EncodeString(k)
151-
if err != nil {
184+
if err := e.EncodeString(k); err != nil {
185+
*sp = keys
186+
putSortedKeys(sp)
152187
return err
153188
}
154-
if err = e.EncodeBool(m[k]); err != nil {
189+
if err := e.EncodeBool(m[k]); err != nil {
190+
*sp = keys
191+
putSortedKeys(sp)
155192
return err
156193
}
157194
}
158195

196+
*sp = keys
197+
putSortedKeys(sp)
159198
return nil
160199
}
161200

162201
func (e *Encoder) encodeSortedMapStringString(m map[string]string) error {
163-
keys := make([]string, 0, len(m))
202+
sp := getSortedKeys(len(m))
203+
keys := *sp
204+
164205
for k := range m {
165206
keys = append(keys, k)
166207
}
167208
sort.Strings(keys)
168209

169210
for _, k := range keys {
170-
err := e.EncodeString(k)
171-
if err != nil {
211+
if err := e.EncodeString(k); err != nil {
212+
*sp = keys
213+
putSortedKeys(sp)
172214
return err
173215
}
174-
if err = e.EncodeString(m[k]); err != nil {
216+
if err := e.EncodeString(m[k]); err != nil {
217+
*sp = keys
218+
putSortedKeys(sp)
175219
return err
176220
}
177221
}
178222

223+
*sp = keys
224+
putSortedKeys(sp)
179225
return nil
180226
}
181227

0 commit comments

Comments
 (0)