rlp: added pooling of streams using sync (#19044)

Prevents reallocation, improves performance
This commit is contained in:
Marius van der Wijden 2019-02-25 11:34:08 +01:00 committed by Péter Szilágyi
parent 872370e3bc
commit 7d881e45bd

@ -26,6 +26,7 @@ import (
"math/big" "math/big"
"reflect" "reflect"
"strings" "strings"
"sync"
) )
var ( var (
@ -48,6 +49,10 @@ var (
errUintOverflow = errors.New("rlp: uint overflow") errUintOverflow = errors.New("rlp: uint overflow")
errNoPointer = errors.New("rlp: interface given to Decode must be a pointer") errNoPointer = errors.New("rlp: interface given to Decode must be a pointer")
errDecodeIntoNil = errors.New("rlp: pointer given to Decode must not be nil") errDecodeIntoNil = errors.New("rlp: pointer given to Decode must not be nil")
streamPool = sync.Pool{
New: func() interface{} { return new(Stream) },
}
) )
// Decoder is implemented by types that require custom RLP // Decoder is implemented by types that require custom RLP
@ -126,17 +131,24 @@ type Decoder interface {
// //
// NewStream(r, limit).Decode(val) // NewStream(r, limit).Decode(val)
func Decode(r io.Reader, val interface{}) error { func Decode(r io.Reader, val interface{}) error {
// TODO: this could use a Stream from a pool. stream := streamPool.Get().(*Stream)
return NewStream(r, 0).Decode(val) defer streamPool.Put(stream)
stream.Reset(r, 0)
return stream.Decode(val)
} }
// DecodeBytes parses RLP data from b into val. // DecodeBytes parses RLP data from b into val.
// Please see the documentation of Decode for the decoding rules. // Please see the documentation of Decode for the decoding rules.
// The input must contain exactly one value and no trailing data. // The input must contain exactly one value and no trailing data.
func DecodeBytes(b []byte, val interface{}) error { func DecodeBytes(b []byte, val interface{}) error {
// TODO: this could use a Stream from a pool.
r := bytes.NewReader(b) r := bytes.NewReader(b)
if err := NewStream(r, uint64(len(b))).Decode(val); err != nil {
stream := streamPool.Get().(*Stream)
defer streamPool.Put(stream)
stream.Reset(r, uint64(len(b)))
if err := stream.Decode(val); err != nil {
return err return err
} }
if r.Len() > 0 { if r.Len() > 0 {
@ -853,6 +865,7 @@ func (s *Stream) Reset(r io.Reader, inputLimit uint64) {
if s.uintbuf == nil { if s.uintbuf == nil {
s.uintbuf = make([]byte, 8) s.uintbuf = make([]byte, 8)
} }
s.byteval = 0
} }
// Kind returns the kind and size of the next value in the // Kind returns the kind and size of the next value in the