Skip to content

Commit ac1c157

Browse files
joeybloggsjoeybloggs
authored andcommitted
reduce allocations.
1 parent 813448a commit ac1c157

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

decoder.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@ func (d *decoder) parseMapData() {
6868
cidx2 = cum + idx2
6969

7070
if rd, ok = d.dm[k[:cidx]]; !ok {
71-
rd = &recursiveData{
72-
keys: make([]key, 0, 8), // initializing with initial capacity of 8 to avoid too many reallocations of the underlying array
73-
}
71+
rd = d.d.keyPool.Get().(*recursiveData)
72+
rd.keys = rd.keys[0:0]
7473
d.dm[k[:cidx]] = rd
7574
}
7675

@@ -106,6 +105,7 @@ func (d *decoder) traverseStruct(v reflect.Value, namespace string) (set bool) {
106105

107106
typ := v.Type()
108107
var nn string // new namespace
108+
first := len(namespace) == 0
109109

110110
// is anonymous struct, cannot parse or cache as
111111
// it has no name to index by and potentially a
@@ -132,7 +132,7 @@ func (d *decoder) traverseStruct(v reflect.Value, namespace string) (set bool) {
132132
key = fld.Name
133133
}
134134

135-
if len(namespace) == 0 {
135+
if first {
136136
nn = key
137137
} else {
138138
nn = namespace + namespaceSeparator + key
@@ -151,7 +151,7 @@ func (d *decoder) traverseStruct(v reflect.Value, namespace string) (set bool) {
151151

152152
for _, f := range s.fields {
153153

154-
if len(namespace) == 0 {
154+
if first {
155155
nn = f.name
156156
} else {
157157
nn = namespace + namespaceSeparator + f.name

form_decoder.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net/url"
66
"reflect"
77
"strings"
8+
"sync"
89
)
910

1011
// DecodeCustomTypeFunc allows for registering/overriding types to be parsed.
@@ -46,6 +47,7 @@ type Decoder struct {
4647
structCache structCacheMap
4748
customTypeFuncs map[reflect.Type]DecodeCustomTypeFunc
4849
maxArraySize int
50+
keyPool *sync.Pool
4951
}
5052

5153
// NewDecoder creates a new decoder instance with sane defaults
@@ -54,6 +56,11 @@ func NewDecoder() *Decoder {
5456
tagName: "form",
5557
structCache: structCacheMap{m: map[reflect.Type]cachedStruct{}},
5658
maxArraySize: 10000,
59+
keyPool: &sync.Pool{New: func() interface{} {
60+
return &recursiveData{
61+
keys: make([]key, 0, 8), // initializing with initial capacity of 8 to avoid too many reallocations of the underlying array
62+
}
63+
}},
5764
}
5865
}
5966

@@ -141,6 +148,10 @@ func (d *Decoder) Decode(v interface{}, values url.Values) (err error) {
141148

142149
dec.traverseStruct(val, "")
143150

151+
for _, v := range dec.dm {
152+
d.keyPool.Put(v)
153+
}
154+
144155
if len(dec.errs) == 0 {
145156
return nil
146157
}

0 commit comments

Comments
 (0)