forked from cerc-io/plugeth
rlp: avoid list header allocation in encoder (#21274)
List headers made up 11% of all allocations during sync. This change removes most of those allocations by keeping the list header values cached in the encoder buffer instead. Since encoder buffers are pooled, list headers are no longer allocated in the common case where an encoder buffer is available for reuse. Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
parent
ec51cbb5fb
commit
8dfd66f701
@ -93,7 +93,7 @@ func EncodeToReader(val interface{}) (size int, r io.Reader, err error) {
|
|||||||
|
|
||||||
type encbuf struct {
|
type encbuf struct {
|
||||||
str []byte // string data, contains everything except list headers
|
str []byte // string data, contains everything except list headers
|
||||||
lheads []*listhead // all list headers
|
lheads []listhead // all list headers
|
||||||
lhsize int // sum of sizes of all encoded list headers
|
lhsize int // sum of sizes of all encoded list headers
|
||||||
sizebuf []byte // 9-byte auxiliary buffer for uint encoding
|
sizebuf []byte // 9-byte auxiliary buffer for uint encoding
|
||||||
}
|
}
|
||||||
@ -137,13 +137,9 @@ var encbufPool = sync.Pool{
|
|||||||
|
|
||||||
func (w *encbuf) reset() {
|
func (w *encbuf) reset() {
|
||||||
w.lhsize = 0
|
w.lhsize = 0
|
||||||
if w.str != nil {
|
|
||||||
w.str = w.str[:0]
|
w.str = w.str[:0]
|
||||||
}
|
|
||||||
if w.lheads != nil {
|
|
||||||
w.lheads = w.lheads[:0]
|
w.lheads = w.lheads[:0]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// encbuf implements io.Writer so it can be passed it into EncodeRLP.
|
// encbuf implements io.Writer so it can be passed it into EncodeRLP.
|
||||||
func (w *encbuf) Write(b []byte) (int, error) {
|
func (w *encbuf) Write(b []byte) (int, error) {
|
||||||
@ -181,13 +177,16 @@ func (w *encbuf) encodeString(b []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *encbuf) list() *listhead {
|
// list adds a new list header to the header stack. It returns the index
|
||||||
lh := &listhead{offset: len(w.str), size: w.lhsize}
|
// of the header. The caller must call listEnd with this index after encoding
|
||||||
w.lheads = append(w.lheads, lh)
|
// the content of the list.
|
||||||
return lh
|
func (w *encbuf) list() int {
|
||||||
|
w.lheads = append(w.lheads, listhead{offset: len(w.str), size: w.lhsize})
|
||||||
|
return len(w.lheads) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *encbuf) listEnd(lh *listhead) {
|
func (w *encbuf) listEnd(index int) {
|
||||||
|
lh := &w.lheads[index]
|
||||||
lh.size = w.size() - lh.offset - lh.size
|
lh.size = w.size() - lh.offset - lh.size
|
||||||
if lh.size < 56 {
|
if lh.size < 56 {
|
||||||
w.lhsize++ // length encoded into kind tag
|
w.lhsize++ // length encoded into kind tag
|
||||||
|
Loading…
Reference in New Issue
Block a user