codec: remove unnecessary allocations in ProtoCodec.MarshalBinaryLengthPrefixed (#6877)

* codec: remove unnecessary allocations in ProtoCodec.MarshalBinaryLengthPrefixed

Improve ProtoCodec.MarshalBinaryLengthPrefixed by removing the need
to use a *bytes.Buffer and instead use an array and invoke
binary.PutUvarint, and directly create the respective length prefixed
concatentation.

With this change we get the following improvement in all dimenions
of throughput, bytes allocated, number of allocations per operation.

```shell
$ benchstat before.txt after.txt
name                                     old time/op    new time/op    delta
ProtoCodecMarshalBinaryLengthPrefixed-8     295ns ± 2%     177ns ± 3%  -39.92%  (p=0.000 n=20+20)

name                                     old speed      new speed      delta
ProtoCodecMarshalBinaryLengthPrefixed-8   505MB/s ± 2%   841MB/s ± 3%  +66.44%  (p=0.000 n=20+20)

name                                     old alloc/op   new alloc/op   delta
ProtoCodecMarshalBinaryLengthPrefixed-8      576B ± 0%      336B ± 0%  -41.67%  (p=0.000 n=20+20)

name                                     old allocs/op  new allocs/op  delta
ProtoCodecMarshalBinaryLengthPrefixed-8      5.00 ± 0%      3.00 ± 0%  -40.00%  (p=0.000 n=20+20)
```

Fixes #6875

* Address @marbar3778's feedback

Use binary.MaxVarintLen64 instead of 10

Co-authored-by: Marko <marbar3778@yahoo.com>

Co-authored-by: Marko <marbar3778@yahoo.com>
Co-authored-by: Aaron Craelius <aaron@regen.network>
This commit is contained in:
Emmanuel T Odeke
2020-07-29 14:39:34 +00:00
committed by GitHub
co-authored by Marko Aaron Craelius
parent c7dab51192
commit cbb68fc6ef
3 changed files with 47 additions and 24 deletions
+3 -11
View File
@@ -1,7 +1,6 @@
package codec
import (
"bytes"
"encoding/binary"
"fmt"
"strings"
@@ -40,16 +39,9 @@ func (pc *ProtoCodec) MarshalBinaryLengthPrefixed(o ProtoMarshaler) ([]byte, err
return nil, err
}
buf := new(bytes.Buffer)
if err := encodeUvarint(buf, uint64(o.Size())); err != nil {
return nil, err
}
if _, err := buf.Write(bz); err != nil {
return nil, err
}
return buf.Bytes(), nil
var sizeBuf [binary.MaxVarintLen64]byte
n := binary.PutUvarint(sizeBuf[:], uint64(o.Size()))
return append(sizeBuf[:n], bz...), nil
}
func (pc *ProtoCodec) MustMarshalBinaryLengthPrefixed(o ProtoMarshaler) []byte {