From d0620b24ecf86b5558db11876997174ff053e62a Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 20 Aug 2021 21:44:02 +0300 Subject: [PATCH] io: simplify BinReader uint buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to c69670c85bf1af1576b1eb93c6eb1adf79c9392a, 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) --- pkg/io/binaryReader.go | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/pkg/io/binaryReader.go b/pkg/io/binaryReader.go index fdcb08249..f0ca81515 100644 --- a/pkg/io/binaryReader.go +++ b/pkg/io/binaryReader.go @@ -16,20 +16,13 @@ const MaxArraySize = 0x1000000 // Used to simplify error handling when reading into a struct with many fields. type BinReader struct { r io.Reader - u64 []byte - u32 []byte - u16 []byte - u8 []byte + uv [8]byte Err error } // NewBinReaderFromIO makes a BinReader from io.Reader. func NewBinReaderFromIO(ior io.Reader) *BinReader { - u64 := make([]byte, 8) - u32 := u64[:4] - u16 := u64[:2] - u8 := u64[:1] - return &BinReader{r: ior, u64: u64, u32: u32, u16: u16, u8: u8} + return &BinReader{r: ior} } // 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 // io.Reader. On read failures it returns zero. func (r *BinReader) ReadU64LE() uint64 { - r.ReadBytes(r.u64) + r.ReadBytes(r.uv[:8]) if r.Err != nil { 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 // io.Reader. On read failures it returns zero. func (r *BinReader) ReadU32LE() uint32 { - r.ReadBytes(r.u32) + r.ReadBytes(r.uv[:4]) if r.Err != nil { 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 // io.Reader. On read failures it returns zero. func (r *BinReader) ReadU16LE() uint16 { - r.ReadBytes(r.u16) + r.ReadBytes(r.uv[:2]) if r.Err != nil { 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 // io.Reader. On read failures it returns zero. func (r *BinReader) ReadU16BE() uint16 { - r.ReadBytes(r.u16) + r.ReadBytes(r.uv[:2]) if r.Err != nil { 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 // returns zero. func (r *BinReader) ReadB() byte { - r.ReadBytes(r.u8) + r.ReadBytes(r.uv[:1]) if r.Err != nil { return 0 } - return r.u8[0] + return r.uv[0] } // ReadBool reads a boolean value encoded in a zero/non-zero byte from the