Slightly optimize readVarInt.

This commit slightly optimizes the readVarInt function in the case of
multiple-byte variable length integers.  It also reduces the amount of
memory garbage it generates.

Before:

BenchmarkReadVarInt1     5000000               386 ns/op
BenchmarkReadVarInt3     5000000               693 ns/op
BenchmarkReadVarInt5     2000000               793 ns/op
BenchmarkReadVarInt9     5000000               709 ns/op

After:

BenchmarkReadVarInt1     5000000               387 ns/op
BenchmarkReadVarInt3     5000000               471 ns/op
BenchmarkReadVarInt5     5000000               575 ns/op
BenchmarkReadVarInt9     5000000               473 ns/op

This is part ef the ongoing effort to optimize serialization as noted in
conformal/btcd#27.
This commit is contained in:
Dave Collins 2013-11-05 21:53:16 -06:00
parent 87ce23d679
commit 6263efcc71

View file

@ -53,8 +53,8 @@ func writeElements(w io.Writer, elements ...interface{}) error {
// readVarInt reads a variable length integer from r and returns it as a uint64. // readVarInt reads a variable length integer from r and returns it as a uint64.
func readVarInt(r io.Reader, pver uint32) (uint64, error) { func readVarInt(r io.Reader, pver uint32) (uint64, error) {
b := make([]byte, 1) b := make([]byte, 8)
_, err := io.ReadFull(r, b) _, err := io.ReadFull(r, b[0:1])
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -63,28 +63,25 @@ func readVarInt(r io.Reader, pver uint32) (uint64, error) {
discriminant := uint8(b[0]) discriminant := uint8(b[0])
switch discriminant { switch discriminant {
case 0xff: case 0xff:
var u uint64 _, err := io.ReadFull(r, b)
err = binary.Read(r, binary.LittleEndian, &u)
if err != nil { if err != nil {
return 0, err return 0, err
} }
rv = u rv = binary.LittleEndian.Uint64(b)
case 0xfe: case 0xfe:
var u uint32 _, err := io.ReadFull(r, b[0:4])
err = binary.Read(r, binary.LittleEndian, &u)
if err != nil { if err != nil {
return 0, err return 0, err
} }
rv = uint64(u) rv = uint64(binary.LittleEndian.Uint32(b))
case 0xfd: case 0xfd:
var u uint16 _, err := io.ReadFull(r, b[0:2])
err = binary.Read(r, binary.LittleEndian, &u)
if err != nil { if err != nil {
return 0, err return 0, err
} }
rv = uint64(u) rv = uint64(binary.LittleEndian.Uint16(b))
default: default:
rv = uint64(discriminant) rv = uint64(discriminant)