Skip to content

Commit 2382197

Browse files
authored
Merge pull request #48 from Basekick-Labs/perf/marshal-append
perf(encode): add MarshalAppend for zero-alloc buffer reuse
2 parents 82f46cf + dfd0082 commit 2382197

2 files changed

Lines changed: 29 additions & 11 deletions

File tree

bench_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,21 @@ func BenchmarkStructMarshal(b *testing.B) {
304304
}
305305
}
306306

307+
func BenchmarkStructMarshalAppend(b *testing.B) {
308+
in := structForBenchmark()
309+
buf := make([]byte, 0, 2048)
310+
311+
b.ResetTimer()
312+
313+
for i := 0; i < b.N; i++ {
314+
var err error
315+
buf, err = msgpack.MarshalAppend(buf[:0], in)
316+
if err != nil {
317+
b.Fatal(err)
318+
}
319+
}
320+
}
321+
307322
func BenchmarkStructUnmarshal(b *testing.B) {
308323
in := structForBenchmark()
309324
buf, err := msgpack.Marshal(in)

encode.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,23 +63,26 @@ func PutEncoder(enc *Encoder) {
6363

6464
// Marshal returns the MessagePack encoding of v.
6565
func Marshal(v interface{}) ([]byte, error) {
66+
return MarshalAppend(nil, v)
67+
}
68+
69+
// MarshalAppend is like Marshal but appends the encoded bytes to dst.
70+
// This allows callers to reuse buffers and reduce allocations:
71+
//
72+
// buf = buf[:0]
73+
// buf, err = msgpack.MarshalAppend(buf, v)
74+
func MarshalAppend(dst []byte, v interface{}) ([]byte, error) {
6675
enc := GetEncoder()
6776
enc.resetForMarshal()
6877

69-
err := enc.Encode(v)
70-
71-
var b []byte
72-
if err == nil {
73-
b = make([]byte, len(enc.wbuf))
74-
copy(b, enc.wbuf)
78+
if err := enc.Encode(v); err != nil {
79+
PutEncoder(enc)
80+
return dst, err
7581
}
7682

83+
dst = append(dst, enc.wbuf...)
7784
PutEncoder(enc)
78-
79-
if err != nil {
80-
return nil, err
81-
}
82-
return b, nil
85+
return dst, nil
8386
}
8487

8588
type Encoder struct {

0 commit comments

Comments
 (0)