Skip to content

Commit f92bb72

Browse files
committed
internal: use a sync.Pool of msgpack.Decoder
The change helps to avoid 2 allocations per a response decoding. You could check the change with the command: $ go test -v . -bench . -run f -benchmem
1 parent c0a8ad3 commit f92bb72

File tree

6 files changed

+70
-27
lines changed

6 files changed

+70
-27
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
1010

1111
### Added
1212

13+
- A usage of sync.Pool of msgpack.Decoder saves 2 object allocations per
14+
a response decoding.
15+
1316
### Changed
1417

1518
- Connect() now retry the connection if a failure occurs and opts.Reconnect > 0.

box_error.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,10 @@ func (e *BoxError) UnmarshalMsgpack(b []byte) error {
278278
}
279279

280280
buf := bytes.NewBuffer(b)
281-
dec := msgpack.NewDecoder(buf)
281+
dec := getDecoder()
282+
defer putDecoder(dec)
283+
284+
dec.Reset(buf)
282285

283286
if val, err := decodeBoxError(dec); err != nil {
284287
return err

connection.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,11 @@ func (conn *Connection) writer(w writeFlusher, c Conn) {
803803
func readWatchEvent(reader io.Reader) (connWatchEvent, error) {
804804
keyExist := false
805805
event := connWatchEvent{}
806-
d := msgpack.NewDecoder(reader)
806+
807+
d := getDecoder()
808+
defer putDecoder(d)
809+
810+
d.Reset(reader)
807811

808812
l, err := d.DecodeMapLen()
809813
if err != nil {

decoder.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package tarantool
2+
3+
import (
4+
"sync"
5+
6+
"github.com/vmihailenco/msgpack/v5"
7+
)
8+
9+
func untypedMapDecoder(dec *msgpack.Decoder) (interface{}, error) {
10+
return dec.DecodeUntypedMap()
11+
}
12+
13+
var decPool = sync.Pool{
14+
New: func() interface{} {
15+
d := msgpack.NewDecoder(nil)
16+
17+
d.SetMapDecoder(untypedMapDecoder)
18+
19+
return d
20+
},
21+
}
22+
23+
func getDecoder() *msgpack.Decoder {
24+
return decPool.Get().(*msgpack.Decoder)
25+
}
26+
27+
func putDecoder(dec *msgpack.Decoder) {
28+
decPool.Put(dec)
29+
}

dial.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,11 @@ func readResponse(r io.Reader, req Request) (Response, error) {
547547
}
548548

549549
buf := smallBuf{b: respBytes}
550-
header, _, err := decodeHeader(msgpack.NewDecoder(&smallBuf{}), &buf)
550+
551+
d := getDecoder()
552+
defer putDecoder(d)
553+
554+
header, _, err := decodeHeader(d, &buf)
551555
if err != nil {
552556
return nil, fmt.Errorf("decode response header error: %w", err)
553557
}

response.go

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,10 @@ func (resp *baseResponse) Decode() ([]interface{}, error) {
329329
var l int
330330
info := &decodeInfo{}
331331

332-
d := msgpack.NewDecoder(&resp.buf)
333-
d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) {
334-
return dec.DecodeUntypedMap()
335-
})
332+
d := getDecoder()
333+
defer putDecoder(d)
334+
335+
d.Reset(&resp.buf)
336336

337337
if l, err = d.DecodeMapLen(); err != nil {
338338
resp.err = err
@@ -384,10 +384,10 @@ func (resp *SelectResponse) Decode() ([]interface{}, error) {
384384
var l int
385385
info := &decodeInfo{}
386386

387-
d := msgpack.NewDecoder(&resp.buf)
388-
d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) {
389-
return dec.DecodeUntypedMap()
390-
})
387+
d := getDecoder()
388+
defer putDecoder(d)
389+
390+
d.Reset(&resp.buf)
391391

392392
if l, err = d.DecodeMapLen(); err != nil {
393393
resp.err = err
@@ -447,10 +447,10 @@ func (resp *ExecuteResponse) Decode() ([]interface{}, error) {
447447
var l int
448448
info := &decodeInfo{}
449449

450-
d := msgpack.NewDecoder(&resp.buf)
451-
d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) {
452-
return dec.DecodeUntypedMap()
453-
})
450+
d := getDecoder()
451+
defer putDecoder(d)
452+
453+
d.Reset(&resp.buf)
454454

455455
if l, err = d.DecodeMapLen(); err != nil {
456456
resp.err = err
@@ -535,10 +535,10 @@ func (resp *baseResponse) DecodeTyped(res interface{}) error {
535535
info := &decodeInfo{}
536536
var l int
537537

538-
d := msgpack.NewDecoder(&resp.buf)
539-
d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) {
540-
return dec.DecodeUntypedMap()
541-
})
538+
d := getDecoder()
539+
defer putDecoder(d)
540+
541+
d.Reset(&resp.buf)
542542

543543
if l, err = d.DecodeMapLen(); err != nil {
544544
return err
@@ -576,10 +576,10 @@ func (resp *SelectResponse) DecodeTyped(res interface{}) error {
576576
info := &decodeInfo{}
577577
var l int
578578

579-
d := msgpack.NewDecoder(&resp.buf)
580-
d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) {
581-
return dec.DecodeUntypedMap()
582-
})
579+
d := getDecoder()
580+
defer putDecoder(d)
581+
582+
d.Reset(&resp.buf)
583583

584584
if l, err = d.DecodeMapLen(); err != nil {
585585
return err
@@ -624,10 +624,10 @@ func (resp *ExecuteResponse) DecodeTyped(res interface{}) error {
624624
info := &decodeInfo{}
625625
var l int
626626

627-
d := msgpack.NewDecoder(&resp.buf)
628-
d.SetMapDecoder(func(dec *msgpack.Decoder) (interface{}, error) {
629-
return dec.DecodeUntypedMap()
630-
})
627+
d := getDecoder()
628+
defer putDecoder(d)
629+
630+
d.Reset(&resp.buf)
631631

632632
if l, err = d.DecodeMapLen(); err != nil {
633633
return err

0 commit comments

Comments
 (0)