encoding/gob: custom array/slice decoders
Use go generate to write better loops for decoding arrays,
just as we did for encoding. It doesn't help as much,
relatively speaking, but it's still noticeable.

benchmark                          old ns/op     new ns/op     delta
BenchmarkDecodeComplex128Slice     202348        184529        -8.81%
BenchmarkDecodeFloat64Slice        135800        120979        -10.91%
BenchmarkDecodeInt32Slice          121200        105149        -13.24%
BenchmarkDecodeStringSlice         288129        278214        -3.44%

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/154420044
diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go
index abfe936..940e5ad 100644
--- a/src/encoding/gob/timing_test.go
+++ b/src/encoding/gob/timing_test.go
@@ -132,13 +132,14 @@
 	}
 }
 
-func BenchmarkComplex128Slice(b *testing.B) {
+func BenchmarkEncodeComplex128Slice(b *testing.B) {
 	var buf bytes.Buffer
 	enc := NewEncoder(&buf)
 	a := make([]complex128, 1000)
 	for i := range a {
 		a[i] = 1.2 + 3.4i
 	}
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		buf.Reset()
 		err := enc.Encode(a)
@@ -148,29 +149,14 @@
 	}
 }
 
-func BenchmarkInt32Slice(b *testing.B) {
-	var buf bytes.Buffer
-	enc := NewEncoder(&buf)
-	a := make([]int32, 1000)
-	for i := range a {
-		a[i] = 1234
-	}
-	for i := 0; i < b.N; i++ {
-		buf.Reset()
-		err := enc.Encode(a)
-		if err != nil {
-			b.Fatal(err)
-		}
-	}
-}
-
-func BenchmarkFloat64Slice(b *testing.B) {
+func BenchmarkEncodeFloat64Slice(b *testing.B) {
 	var buf bytes.Buffer
 	enc := NewEncoder(&buf)
 	a := make([]float64, 1000)
 	for i := range a {
 		a[i] = 1.23e4
 	}
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		buf.Reset()
 		err := enc.Encode(a)
@@ -180,13 +166,31 @@
 	}
 }
 
-func BenchmarkStringSlice(b *testing.B) {
+func BenchmarkEncodeInt32Slice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]int32, 1000)
+	for i := range a {
+		a[i] = 1234
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		err := enc.Encode(a)
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
+func BenchmarkEncodeStringSlice(b *testing.B) {
 	var buf bytes.Buffer
 	enc := NewEncoder(&buf)
 	a := make([]string, 1000)
 	for i := range a {
 		a[i] = "now is the time"
 	}
+	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		buf.Reset()
 		err := enc.Encode(a)
@@ -195,3 +199,127 @@
 		}
 	}
 }
+
+// benchmarkBuf is a read buffer we can reset
+type benchmarkBuf struct {
+	offset int
+	data   []byte
+}
+
+func (b *benchmarkBuf) Read(p []byte) (n int, err error) {
+	n = copy(p, b.data[b.offset:])
+	if n == 0 {
+		return 0, io.EOF
+	}
+	b.offset += n
+	return
+}
+
+func (b *benchmarkBuf) ReadByte() (c byte, err error) {
+	if b.offset >= len(b.data) {
+		return 0, io.EOF
+	}
+	c = b.data[b.offset]
+	b.offset++
+	return
+}
+
+func (b *benchmarkBuf) reset() {
+	b.offset = 0
+}
+
+func BenchmarkDecodeComplex128Slice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]complex128, 1000)
+	for i := range a {
+		a[i] = 1.2 + 3.4i
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		b.Fatal(err)
+	}
+	x := make([]complex128, 1000)
+	bbuf := benchmarkBuf{data: buf.Bytes()}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bbuf.reset()
+		dec := NewDecoder(&bbuf)
+		err := dec.Decode(&x)
+		if err != nil {
+			b.Fatal(i, err)
+		}
+	}
+}
+
+func BenchmarkDecodeFloat64Slice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]float64, 1000)
+	for i := range a {
+		a[i] = 1.23e4
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		b.Fatal(err)
+	}
+	x := make([]float64, 1000)
+	bbuf := benchmarkBuf{data: buf.Bytes()}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bbuf.reset()
+		dec := NewDecoder(&bbuf)
+		err := dec.Decode(&x)
+		if err != nil {
+			b.Fatal(i, err)
+		}
+	}
+}
+
+func BenchmarkDecodeInt32Slice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]int32, 1000)
+	for i := range a {
+		a[i] = 1234
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		b.Fatal(err)
+	}
+	x := make([]int32, 1000)
+	bbuf := benchmarkBuf{data: buf.Bytes()}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bbuf.reset()
+		dec := NewDecoder(&bbuf)
+		err := dec.Decode(&x)
+		if err != nil {
+			b.Fatal(i, err)
+		}
+	}
+}
+
+func BenchmarkDecodeStringSlice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]string, 1000)
+	for i := range a {
+		a[i] = "now is the time"
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		b.Fatal(err)
+	}
+	x := make([]string, 1000)
+	bbuf := benchmarkBuf{data: buf.Bytes()}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bbuf.reset()
+		dec := NewDecoder(&bbuf)
+		err := dec.Decode(&x)
+		if err != nil {
+			b.Fatal(i, err)
+		}
+	}
+}