rlp, eth: batch-allocate headers and reuse stream in decode path

This commit is contained in:
Sahil Sojitra 2026-05-22 17:11:42 +05:30
parent fc19b63105
commit 17ecac6a16
2 changed files with 28 additions and 3 deletions

View file

@ -21,6 +21,7 @@ import (
"encoding/json"
"fmt"
"math"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@ -374,15 +375,31 @@ func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error {
}, metadata)
}
type headerAlloc struct {
header types.Header
difficulty big.Int
number big.Int
}
func decodeBlockHeaders(list *rlp.RawList[*types.Header]) ([]*types.Header, error) {
headers := make([]*types.Header, 0, list.Len())
stream := rlp.NewBytesStream(nil)
defer rlp.PutStream(stream)
it := list.ContentIterator()
for it.Next() {
header := new(types.Header)
if err := types.DecodeHeader(it.Value(), header); err != nil {
a := new(headerAlloc)
a.header.Difficulty = &a.difficulty
a.header.Number = &a.number
stream.ResetBytes(it.Value())
if err := a.header.DecodeRLP(stream); err != nil {
return headers, err
}
headers = append(headers, header)
if stream.Remaining() != 0 {
return headers, rlp.ErrMoreThanOneValue
}
headers = append(headers, &a.header)
}
return headers, nil
}

View file

@ -642,6 +642,14 @@ func PutStream(stream *Stream) {
streamPool.Put(stream)
}
// ResetBytes resets the stream to decode from b, reusing the inline slice
// reader. This allows decoding a batch of values with one pooled stream
// instead of doing a pool round-trip per value.
func (s *Stream) ResetBytes(b []byte) {
s.sliceRdr = b
s.Reset(&s.sliceRdr, uint64(len(b)))
}
// NewListStream creates a new stream that pretends to be positioned
// at an encoded list of the given length.
func NewListStream(r io.Reader, len uint64) *Stream {