Skip to content
Permalink
Browse files

loader: avoid reader interface conversion

Converting R to ByteReader causes a convI2I call, and it's not necessary
in order to call one of its methods.  Varuint32() dominates CPU profile.

benchmark                   old ns/op     new ns/op     delta
BenchmarkLoad001/Init-8     103866        52783         -49.18%
BenchmarkLoad001/Code-8     35597441      30571208      -14.12%
BenchmarkLoad001/Data-8     1676          1538          -8.23%

benchmark                   old MB/s     new MB/s     speedup
BenchmarkLoad001/Init-8     43.76        86.11        1.97x
BenchmarkLoad001/Code-8     26.74        31.14        1.16x
  • Loading branch information...
tsavola committed Feb 15, 2019
1 parent 1502941 commit e28fe3f83dbb7b1fb68a608404d7d9815241da94
Showing with 31 additions and 15 deletions.
  1. +31 −15 internal/loader/loader.go
@@ -7,7 +7,6 @@ package loader
import (
"encoding/binary"
"io"
"math"

"github.com/tsavola/wag/internal/module"
"github.com/tsavola/wag/internal/reader"
@@ -86,23 +85,40 @@ func (load L) Varuint1() bool {
return x == 1
}

func (load L) Varuint32() uint32 {
x, err := binary.ReadUvarint(load.R)
if err != nil {
panic(module.WrapError(err, "varuint32 read error"))
}
if x > math.MaxUint32 {
panic(module.Errorf("varuint32 is too large: 0x%x", x))
func (load L) Varuint32() (x uint32) {
var shift uint
for n := 1; ; n++ {
b, err := load.R.ReadByte()
if err != nil {
panic(err)
}
if b < 0x80 {
if n > 5 || n == 5 && b > 0xf {
panic(module.Error("varuint32 is too large"))
}
return x | uint32(b)<<shift
}
x |= (uint32(b) & 0x7f) << shift
shift += 7
}
return uint32(x)
}

func (load L) Varuint64() (x uint64) {
x, err := binary.ReadUvarint(load.R)
if err != nil {
panic(module.WrapError(err, "varuint64 read error"))
var shift uint
for n := 1; ; n++ {
b, err := load.R.ReadByte()
if err != nil {
panic(err)
}
if b < 0x80 {
if n > 9 || n == 9 && b > 1 {
panic(module.Error("varuint64 is too large"))
}
return x | uint64(b)<<shift
}
x |= (uint64(b) & 0x7f) << shift
shift += 7
}
return
}

// Count reads a varuint32 for iteration.
@@ -114,7 +130,7 @@ func (load L) Count(maxCount uint32, name string) []struct{} {
return make([]struct{}, int(count))
}

func Varuint32(r io.ByteReader) (x uint32, n int, err error) {
func Varuint32(r reader.R) (x uint32, n int, err error) {
var shift uint
for n = 1; ; n++ {
var b byte
@@ -124,7 +140,7 @@ func Varuint32(r io.ByteReader) (x uint32, n int, err error) {
}
if b < 0x80 {
if n > 5 || n == 5 && b > 0xf {
err = module.Errorf("varuint32 is too large")
err = module.Error("varuint32 is too large")
return
}
x |= uint32(b) << shift

0 comments on commit e28fe3f

Please sign in to comment.
You can’t perform that action at this time.