aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/binary
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josharian@gmail.com>2018-03-05 07:40:14 -0800
committerJosh Bleecher Snyder <josharian@gmail.com>2018-03-06 18:59:03 +0000
commitb85433975aedc2be2971093b6bbb0a7dc264c8fd (patch)
tree961c9a4338f1d84cd30c8ec6e24cfb4b7fd6d168 /src/encoding/binary
parentf7739c07c8f6ef9bfa28e8c4a4527b01cf3991bc (diff)
downloadgo-b85433975aedc2be2971093b6bbb0a7dc264c8fd.tar.gz
go-b85433975aedc2be2971093b6bbb0a7dc264c8fd.zip
encoding/binary: use an offset instead of slicing
While running make.bash, over 5% of all pointer writes come from encoding/binary doing struct reads. This change replaces slicing during such reads with an offset. This avoids updating the slice pointer with every struct field read or write. This has no impact when the write barrier is off. Running the benchmarks with GOGC=1, however, shows significant improvement: name old time/op new time/op delta ReadStruct-8 13.2µs ± 6% 10.1µs ± 5% -23.24% (p=0.000 n=10+10) name old speed new speed delta ReadStruct-8 5.69MB/s ± 6% 7.40MB/s ± 5% +30.18% (p=0.000 n=10+10) Change-Id: I22904263196bfeddc38abe8989428e263aee5253 Reviewed-on: https://go-review.googlesource.com/98757 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/encoding/binary')
-rw-r--r--src/encoding/binary/binary.go56
1 files changed, 29 insertions, 27 deletions
diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go
index 2d01a3cb28..22fd7f2a80 100644
--- a/src/encoding/binary/binary.go
+++ b/src/encoding/binary/binary.go
@@ -419,70 +419,71 @@ func sizeof(t reflect.Type) int {
}
type coder struct {
- order ByteOrder
- buf []byte
+ order ByteOrder
+ buf []byte
+ offset int
}
type decoder coder
type encoder coder
func (d *decoder) bool() bool {
- x := d.buf[0]
- d.buf = d.buf[1:]
+ x := d.buf[d.offset]
+ d.offset++
return x != 0
}
func (e *encoder) bool(x bool) {
if x {
- e.buf[0] = 1
+ e.buf[e.offset] = 1
} else {
- e.buf[0] = 0
+ e.buf[e.offset] = 0
}
- e.buf = e.buf[1:]
+ e.offset++
}
func (d *decoder) uint8() uint8 {
- x := d.buf[0]
- d.buf = d.buf[1:]
+ x := d.buf[d.offset]
+ d.offset++
return x
}
func (e *encoder) uint8(x uint8) {
- e.buf[0] = x
- e.buf = e.buf[1:]
+ e.buf[e.offset] = x
+ e.offset++
}
func (d *decoder) uint16() uint16 {
- x := d.order.Uint16(d.buf[0:2])
- d.buf = d.buf[2:]
+ x := d.order.Uint16(d.buf[d.offset : d.offset+2])
+ d.offset += 2
return x
}
func (e *encoder) uint16(x uint16) {
- e.order.PutUint16(e.buf[0:2], x)
- e.buf = e.buf[2:]
+ e.order.PutUint16(e.buf[e.offset:e.offset+2], x)
+ e.offset += 2
}
func (d *decoder) uint32() uint32 {
- x := d.order.Uint32(d.buf[0:4])
- d.buf = d.buf[4:]
+ x := d.order.Uint32(d.buf[d.offset : d.offset+4])
+ d.offset += 4
return x
}
func (e *encoder) uint32(x uint32) {
- e.order.PutUint32(e.buf[0:4], x)
- e.buf = e.buf[4:]
+ e.order.PutUint32(e.buf[e.offset:e.offset+4], x)
+ e.offset += 4
}
func (d *decoder) uint64() uint64 {
- x := d.order.Uint64(d.buf[0:8])
- d.buf = d.buf[8:]
+ x := d.order.Uint64(d.buf[d.offset : d.offset+8])
+ d.offset += 8
return x
}
func (e *encoder) uint64(x uint64) {
- e.order.PutUint64(e.buf[0:8], x)
- e.buf = e.buf[8:]
+ e.order.PutUint64(e.buf[e.offset:e.offset+8], x)
+ e.offset += 8
}
func (d *decoder) int8() int8 { return int8(d.uint8()) }
@@ -646,15 +647,16 @@ func (e *encoder) value(v reflect.Value) {
}
func (d *decoder) skip(v reflect.Value) {
- d.buf = d.buf[dataSize(v):]
+ d.offset += dataSize(v)
}
func (e *encoder) skip(v reflect.Value) {
n := dataSize(v)
- for i := range e.buf[0:n] {
- e.buf[i] = 0
+ zero := e.buf[e.offset : e.offset+n]
+ for i := range zero {
+ zero[i] = 0
}
- e.buf = e.buf[n:]
+ e.offset += n
}
// intDataSize returns the size of the data required to represent the data when encoded.