]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/binary: use an offset instead of slicing
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 5 Mar 2018 15:40:14 +0000 (07:40 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 6 Mar 2018 18:59:03 +0000 (18:59 +0000)
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>
src/encoding/binary/binary.go

index 2d01a3cb287b5dc32201e64c50a8ae5db65ab6a5..22fd7f2a8005dcc4ae76179a5e227881a5715249 100644 (file)
@@ -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.