io: use a single slice for numbers

Slice takes 24 bytes of memory, while we really need only 9.
```
name                 old time/op    new time/op    delta
Transaction_Bytes-8     667ns ±17%     583ns ± 6%  -12.50%  (p=0.000 n=10+10)
GetVarSize-8            283ns ±11%     189ns ± 5%  -33.37%  (p=0.000 n=10+10)

name                 old alloc/op   new alloc/op   delta
Transaction_Bytes-8    1.01kB ± 0%    0.88kB ± 0%  -12.70%  (p=0.000 n=10+10)
GetVarSize-8             184B ± 0%       56B ± 0%  -69.57%  (p=0.000 n=10+10)

name                 old allocs/op  new allocs/op  delta
Transaction_Bytes-8      7.00 ± 0%      6.00 ± 0%  -14.29%  (p=0.000 n=10+10)
GetVarSize-8             3.00 ± 0%      2.00 ± 0%  -33.33%  (p=0.000 n=10+10)
```

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgeniy Stratonikov 2021-08-06 10:45:27 +03:00
parent 620295efe3
commit c69670c85b

View file

@ -11,56 +11,47 @@ import (
// from a struct with many fields. // from a struct with many fields.
type BinWriter struct { type BinWriter struct {
w io.Writer w io.Writer
uv []byte
u64 []byte
u32 []byte
u16 []byte
u8 []byte
Err error Err error
uv [9]byte
} }
// NewBinWriterFromIO makes a BinWriter from io.Writer. // NewBinWriterFromIO makes a BinWriter from io.Writer.
func NewBinWriterFromIO(iow io.Writer) *BinWriter { func NewBinWriterFromIO(iow io.Writer) *BinWriter {
uv := make([]byte, 9) return &BinWriter{w: iow}
u64 := uv[:8]
u32 := u64[:4]
u16 := u64[:2]
u8 := u64[:1]
return &BinWriter{w: iow, uv: uv, u64: u64, u32: u32, u16: u16, u8: u8}
} }
// WriteU64LE writes an uint64 value into the underlying io.Writer in // WriteU64LE writes an uint64 value into the underlying io.Writer in
// little-endian format. // little-endian format.
func (w *BinWriter) WriteU64LE(u64 uint64) { func (w *BinWriter) WriteU64LE(u64 uint64) {
binary.LittleEndian.PutUint64(w.u64, u64) binary.LittleEndian.PutUint64(w.uv[:8], u64)
w.WriteBytes(w.u64) w.WriteBytes(w.uv[:8])
} }
// WriteU32LE writes an uint32 value into the underlying io.Writer in // WriteU32LE writes an uint32 value into the underlying io.Writer in
// little-endian format. // little-endian format.
func (w *BinWriter) WriteU32LE(u32 uint32) { func (w *BinWriter) WriteU32LE(u32 uint32) {
binary.LittleEndian.PutUint32(w.u32, u32) binary.LittleEndian.PutUint32(w.uv[:4], u32)
w.WriteBytes(w.u32) w.WriteBytes(w.uv[:4])
} }
// WriteU16LE writes an uint16 value into the underlying io.Writer in // WriteU16LE writes an uint16 value into the underlying io.Writer in
// little-endian format. // little-endian format.
func (w *BinWriter) WriteU16LE(u16 uint16) { func (w *BinWriter) WriteU16LE(u16 uint16) {
binary.LittleEndian.PutUint16(w.u16, u16) binary.LittleEndian.PutUint16(w.uv[:2], u16)
w.WriteBytes(w.u16) w.WriteBytes(w.uv[:2])
} }
// WriteU16BE writes an uint16 value into the underlying io.Writer in // WriteU16BE writes an uint16 value into the underlying io.Writer in
// big-endian format. // big-endian format.
func (w *BinWriter) WriteU16BE(u16 uint16) { func (w *BinWriter) WriteU16BE(u16 uint16) {
binary.BigEndian.PutUint16(w.u16, u16) binary.BigEndian.PutUint16(w.uv[:2], u16)
w.WriteBytes(w.u16) w.WriteBytes(w.uv[:2])
} }
// WriteB writes a byte into the underlying io.Writer. // WriteB writes a byte into the underlying io.Writer.
func (w *BinWriter) WriteB(u8 byte) { func (w *BinWriter) WriteB(u8 byte) {
w.u8[0] = u8 w.uv[0] = u8
w.WriteBytes(w.u8) w.WriteBytes(w.uv[:1])
} }
// WriteBool writes a boolean value into the underlying io.Writer encoded as // WriteBool writes a boolean value into the underlying io.Writer encoded as
@ -108,7 +99,7 @@ func (w *BinWriter) WriteVarUint(val uint64) {
return return
} }
n := PutVarUint(w.uv, val) n := PutVarUint(w.uv[:], val)
w.WriteBytes(w.uv[:n]) w.WriteBytes(w.uv[:n])
} }