mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/types: reduce allocation when decoding typed transactions and receipts
This commit is contained in:
parent
e4a28340c4
commit
353c1d3ee0
3 changed files with 34 additions and 4 deletions
|
|
@ -18,6 +18,8 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -36,6 +38,21 @@ var encodeBufferPool = sync.Pool{
|
||||||
New: func() interface{} { return new(bytes.Buffer) },
|
New: func() interface{} { return new(bytes.Buffer) },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPooledBuffer retrieves a buffer from the pool and creates a byte slice
|
||||||
|
// of the requested size from it.
|
||||||
|
//
|
||||||
|
// The caller should return the Buffer object back into encodeBufferPool after use!
|
||||||
|
func getPooledBuffer(size uint64) ([]byte, *bytes.Buffer, error) {
|
||||||
|
if size > math.MaxInt {
|
||||||
|
return nil, nil, fmt.Errorf("can't get buffer of size %d", size)
|
||||||
|
}
|
||||||
|
buf := encodeBufferPool.Get().(*bytes.Buffer)
|
||||||
|
buf.Reset()
|
||||||
|
buf.Grow(int(size))
|
||||||
|
b := buf.Bytes()[:int(size)]
|
||||||
|
return b, buf, nil
|
||||||
|
}
|
||||||
|
|
||||||
// rlpHash encodes x and hashes the encoded bytes.
|
// rlpHash encodes x and hashes the encoded bytes.
|
||||||
func rlpHash(x interface{}) (h common.Hash) {
|
func rlpHash(x interface{}) (h common.Hash) {
|
||||||
sha := hasherPool.Get().(crypto.KeccakState)
|
sha := hasherPool.Get().(crypto.KeccakState)
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ func (r *Receipt) MarshalBinary() ([]byte, error) {
|
||||||
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
|
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
|
||||||
// from an RLP stream.
|
// from an RLP stream.
|
||||||
func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
kind, _, err := s.Kind()
|
kind, size, err := s.Kind()
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return err
|
return err
|
||||||
|
|
@ -167,7 +167,14 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
return r.setFromRLP(dec)
|
return r.setFromRLP(dec)
|
||||||
default:
|
default:
|
||||||
// It's an EIP-2718 typed tx receipt.
|
// It's an EIP-2718 typed tx receipt.
|
||||||
b, err := s.Bytes()
|
b, buf, err := getPooledBuffer(size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer encodeBufferPool.Put(buf)
|
||||||
|
if err := s.ReadBytes(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,10 +147,16 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error {
|
||||||
return err
|
return err
|
||||||
default:
|
default:
|
||||||
// It's an EIP-2718 typed TX envelope.
|
// It's an EIP-2718 typed TX envelope.
|
||||||
var b []byte
|
// First read the tx payload bytes into a temporary buffer.
|
||||||
if b, err = s.Bytes(); err != nil {
|
b, buf, err := getPooledBuffer(size)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer encodeBufferPool.Put(buf)
|
||||||
|
if err := s.ReadBytes(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Now decode the inner transaction.
|
||||||
inner, err := tx.decodeTyped(b)
|
inner, err := tx.decodeTyped(b)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tx.setDecoded(inner, uint64(len(b)))
|
tx.setDecoded(inner, uint64(len(b)))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue