io: simplify BinReader uint buffer

Similar to c69670c85b, allows to eliminate one
allocation and reduce memory footprint a bit (tested on tx decoding):

name               old time/op    new time/op    delta
DecodeFromBytes-8    1.78µs ± 3%    1.79µs ± 2%    ~     (p=1.000 n=10+10)

name               old alloc/op   new alloc/op   delta
DecodeFromBytes-8      888B ± 0%      800B ± 0%  -9.91%  (p=0.000 n=10+10)

name               old allocs/op  new allocs/op  delta
DecodeFromBytes-8      11.0 ± 0%      10.0 ± 0%  -9.09%  (p=0.000 n=10+10)
This commit is contained in:
Roman Khimov 2021-08-20 21:44:02 +03:00
parent 1a733ca456
commit d0620b24ec

View file

@ -16,20 +16,13 @@ const MaxArraySize = 0x1000000
// Used to simplify error handling when reading into a struct with many fields. // Used to simplify error handling when reading into a struct with many fields.
type BinReader struct { type BinReader struct {
r io.Reader r io.Reader
u64 []byte uv [8]byte
u32 []byte
u16 []byte
u8 []byte
Err error Err error
} }
// NewBinReaderFromIO makes a BinReader from io.Reader. // NewBinReaderFromIO makes a BinReader from io.Reader.
func NewBinReaderFromIO(ior io.Reader) *BinReader { func NewBinReaderFromIO(ior io.Reader) *BinReader {
u64 := make([]byte, 8) return &BinReader{r: ior}
u32 := u64[:4]
u16 := u64[:2]
u8 := u64[:1]
return &BinReader{r: ior, u64: u64, u32: u32, u16: u16, u8: u8}
} }
// NewBinReaderFromBuf makes a BinReader from byte buffer. // NewBinReaderFromBuf makes a BinReader from byte buffer.
@ -41,51 +34,51 @@ func NewBinReaderFromBuf(b []byte) *BinReader {
// ReadU64LE reads a little-endian encoded uint64 value from the underlying // ReadU64LE reads a little-endian encoded uint64 value from the underlying
// io.Reader. On read failures it returns zero. // io.Reader. On read failures it returns zero.
func (r *BinReader) ReadU64LE() uint64 { func (r *BinReader) ReadU64LE() uint64 {
r.ReadBytes(r.u64) r.ReadBytes(r.uv[:8])
if r.Err != nil { if r.Err != nil {
return 0 return 0
} }
return binary.LittleEndian.Uint64(r.u64) return binary.LittleEndian.Uint64(r.uv[:8])
} }
// ReadU32LE reads a little-endian encoded uint32 value from the underlying // ReadU32LE reads a little-endian encoded uint32 value from the underlying
// io.Reader. On read failures it returns zero. // io.Reader. On read failures it returns zero.
func (r *BinReader) ReadU32LE() uint32 { func (r *BinReader) ReadU32LE() uint32 {
r.ReadBytes(r.u32) r.ReadBytes(r.uv[:4])
if r.Err != nil { if r.Err != nil {
return 0 return 0
} }
return binary.LittleEndian.Uint32(r.u32) return binary.LittleEndian.Uint32(r.uv[:4])
} }
// ReadU16LE reads a little-endian encoded uint16 value from the underlying // ReadU16LE reads a little-endian encoded uint16 value from the underlying
// io.Reader. On read failures it returns zero. // io.Reader. On read failures it returns zero.
func (r *BinReader) ReadU16LE() uint16 { func (r *BinReader) ReadU16LE() uint16 {
r.ReadBytes(r.u16) r.ReadBytes(r.uv[:2])
if r.Err != nil { if r.Err != nil {
return 0 return 0
} }
return binary.LittleEndian.Uint16(r.u16) return binary.LittleEndian.Uint16(r.uv[:2])
} }
// ReadU16BE reads a big-endian encoded uint16 value from the underlying // ReadU16BE reads a big-endian encoded uint16 value from the underlying
// io.Reader. On read failures it returns zero. // io.Reader. On read failures it returns zero.
func (r *BinReader) ReadU16BE() uint16 { func (r *BinReader) ReadU16BE() uint16 {
r.ReadBytes(r.u16) r.ReadBytes(r.uv[:2])
if r.Err != nil { if r.Err != nil {
return 0 return 0
} }
return binary.BigEndian.Uint16(r.u16) return binary.BigEndian.Uint16(r.uv[:2])
} }
// ReadB reads a byte from the underlying io.Reader. On read failures it // ReadB reads a byte from the underlying io.Reader. On read failures it
// returns zero. // returns zero.
func (r *BinReader) ReadB() byte { func (r *BinReader) ReadB() byte {
r.ReadBytes(r.u8) r.ReadBytes(r.uv[:1])
if r.Err != nil { if r.Err != nil {
return 0 return 0
} }
return r.u8[0] return r.uv[0]
} }
// ReadBool reads a boolean value encoded in a zero/non-zero byte from the // ReadBool reads a boolean value encoded in a zero/non-zero byte from the