|
|
@@ -5,12 +5,9 @@ import (
|
|
|
"io"
|
|
|
"math/big"
|
|
|
"reflect"
|
|
|
+ "sync"
|
|
|
)
|
|
|
|
|
|
-// TODO: put encbufs in a sync.Pool.
|
|
|
-// Doing that requires zeroing the buffers after use.
|
|
|
-// encReader will need to drop it's buffer when done.
|
|
|
-
|
|
|
var (
|
|
|
// Common encoded values.
|
|
|
// These are useful when implementing EncodeRLP.
|
|
|
@@ -112,7 +109,9 @@ func Encode(w io.Writer, val interface{}) error {
|
|
|
// Avoid copying by writing to the outer encbuf directly.
|
|
|
return outer.encode(val)
|
|
|
}
|
|
|
- eb := newencbuf()
|
|
|
+ eb := encbufPool.Get().(*encbuf)
|
|
|
+ eb.reset()
|
|
|
+ defer encbufPool.Put(eb)
|
|
|
if err := eb.encode(val); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
@@ -122,7 +121,9 @@ func Encode(w io.Writer, val interface{}) error {
|
|
|
// EncodeBytes returns the RLP encoding of val.
|
|
|
// Please see the documentation of Encode for the encoding rules.
|
|
|
func EncodeToBytes(val interface{}) ([]byte, error) {
|
|
|
- eb := newencbuf()
|
|
|
+ eb := encbufPool.Get().(*encbuf)
|
|
|
+ eb.reset()
|
|
|
+ defer encbufPool.Put(eb)
|
|
|
if err := eb.encode(val); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
@@ -135,7 +136,8 @@ func EncodeToBytes(val interface{}) ([]byte, error) {
|
|
|
//
|
|
|
// Please see the documentation of Encode for the encoding rules.
|
|
|
func EncodeToReader(val interface{}) (size int, r io.Reader, err error) {
|
|
|
- eb := newencbuf()
|
|
|
+ eb := encbufPool.Get().(*encbuf)
|
|
|
+ eb.reset()
|
|
|
if err := eb.encode(val); err != nil {
|
|
|
return 0, nil, err
|
|
|
}
|
|
|
@@ -182,8 +184,19 @@ func puthead(buf []byte, smalltag, largetag byte, size uint64) int {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func newencbuf() *encbuf {
|
|
|
- return &encbuf{sizebuf: make([]byte, 9)}
|
|
|
+// encbufs are pooled.
|
|
|
+var encbufPool = sync.Pool{
|
|
|
+ New: func() interface{} { return &encbuf{sizebuf: make([]byte, 9)} },
|
|
|
+}
|
|
|
+
|
|
|
+func (w *encbuf) reset() {
|
|
|
+ w.lhsize = 0
|
|
|
+ if w.str != nil {
|
|
|
+ w.str = w.str[:0]
|
|
|
+ }
|
|
|
+ if w.lheads != nil {
|
|
|
+ w.lheads = w.lheads[:0]
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// encbuf implements io.Writer so it can be passed it into EncodeRLP.
|
|
|
@@ -295,6 +308,8 @@ type encReader struct {
|
|
|
func (r *encReader) Read(b []byte) (n int, err error) {
|
|
|
for {
|
|
|
if r.piece = r.next(); r.piece == nil {
|
|
|
+ encbufPool.Put(r.buf)
|
|
|
+ r.buf = nil
|
|
|
return n, io.EOF
|
|
|
}
|
|
|
nn := copy(b[n:], r.piece)
|
|
|
@@ -313,6 +328,9 @@ func (r *encReader) Read(b []byte) (n int, err error) {
|
|
|
// it returns nil at EOF.
|
|
|
func (r *encReader) next() []byte {
|
|
|
switch {
|
|
|
+ case r.buf == nil:
|
|
|
+ return nil
|
|
|
+
|
|
|
case r.piece != nil:
|
|
|
// There is still data available for reading.
|
|
|
return r.piece
|