diff options
author | Felix Lange <fjl@twurst.com> | 2015-06-25 20:48:08 +0800 |
---|---|---|
committer | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-06-30 00:51:47 +0800 |
commit | 3d0c6a8345b28b33eb0dfc4a53b967461977706a (patch) | |
tree | 41076c02d74c72c5ad8d329176b3148806b6e2a1 /rlp | |
parent | c3d62280238de7c98f0487e9d5872eedd2630df1 (diff) | |
download | go-tangerine-3d0c6a8345b28b33eb0dfc4a53b967461977706a.tar.gz go-tangerine-3d0c6a8345b28b33eb0dfc4a53b967461977706a.tar.zst go-tangerine-3d0c6a8345b28b33eb0dfc4a53b967461977706a.zip |
rlp: pool encoder allocations
Diffstat (limited to 'rlp')
-rw-r--r-- | rlp/encode.go | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/rlp/encode.go b/rlp/encode.go index 10ff0ae79..dddde766f 100644 --- a/rlp/encode.go +++ b/rlp/encode.go @@ -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 |