encoding/gob: reduce the amount of memory allocations.

Benchmark results:

benchmark                              old ns/op     new ns/op     delta
BenchmarkEndToEndPipe-4                7547          7294          -3.35%
BenchmarkEndToEndByteBuffer-4          5146          5092          -1.05%
BenchmarkEndToEndSliceByteBuffer-4     552779        439768        -20.44%
BenchmarkEncodeComplex128Slice-4       266370        266184        -0.07%
BenchmarkEncodeFloat64Slice-4          111891        110258        -1.46%
BenchmarkEncodeInt32Slice-4            74482         74080         -0.54%
BenchmarkEncodeStringSlice-4           84404         84279         -0.15%
BenchmarkEncodeInterfaceSlice-4        3942925       3045995       -22.75%
BenchmarkDecodeComplex128Slice-4       451837        415282        -8.09%
BenchmarkDecodeFloat64Slice-4          283584        262558        -7.41%
BenchmarkDecodeInt32Slice-4            246571        237383        -3.73%
BenchmarkDecodeStringSlice-4           734210        479625        -34.67%
BenchmarkDecodeInterfaceSlice-4        4778225       4160935       -12.92%

benchmark                              old allocs     new allocs     delta
BenchmarkEndToEndPipe-4                3              2              -33.33%
BenchmarkEndToEndByteBuffer-4          3              2              -33.33%
BenchmarkEndToEndSliceByteBuffer-4     1002           402            -59.88%
BenchmarkEncodeComplex128Slice-4       1              1              +0.00%
BenchmarkEncodeFloat64Slice-4          1              1              +0.00%
BenchmarkEncodeInt32Slice-4            1              1              +0.00%
BenchmarkEncodeStringSlice-4           1              1              +0.00%
BenchmarkEncodeInterfaceSlice-4        3001           1              -99.97%
BenchmarkDecodeComplex128Slice-4       188            185            -1.60%
BenchmarkDecodeFloat64Slice-4          188            185            -1.60%
BenchmarkDecodeInt32Slice-4            188            185            -1.60%
BenchmarkDecodeStringSlice-4           2188           1185           -45.84%
BenchmarkDecodeInterfaceSlice-4        6197           4194           -32.32%

benchmark                              old bytes     new bytes     delta
BenchmarkEndToEndPipe-4                64            48            -25.00%
BenchmarkEndToEndByteBuffer-4          64            48            -25.00%
BenchmarkEndToEndSliceByteBuffer-4     34551         10554         -69.45%
BenchmarkEncodeComplex128Slice-4       55            55            +0.00%
BenchmarkEncodeFloat64Slice-4          33            33            +0.00%
BenchmarkEncodeInt32Slice-4            32            32            +0.00%
BenchmarkEncodeStringSlice-4           36            36            +0.00%
BenchmarkEncodeInterfaceSlice-4        144555        347           -99.76%
BenchmarkDecodeComplex128Slice-4       28240         28097         -0.51%
BenchmarkDecodeFloat64Slice-4          11840         11697         -1.21%
BenchmarkDecodeInt32Slice-4            10817         10673         -1.33%
BenchmarkDecodeStringSlice-4           56128         39985         -28.76%
BenchmarkDecodeInterfaceSlice-4        132565        100421        -24.25%

Change-Id: Ief7c7706b1f2916486ab7190b81aafbb16b70f1e
Reviewed-on: https://go-review.googlesource.com/13660
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go
index 940e5ad..424b7e6 100644
--- a/src/encoding/gob/timing_test.go
+++ b/src/encoding/gob/timing_test.go
@@ -127,8 +127,8 @@
 			t.Fatal("decode:", err)
 		}
 	})
-	if allocs != 4 {
-		t.Fatalf("mallocs per decode of type Bench: %v; wanted 4\n", allocs)
+	if allocs != 3 {
+		t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\n", allocs)
 	}
 }
 
@@ -200,6 +200,23 @@
 	}
 }
 
+func BenchmarkEncodeInterfaceSlice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]interface{}, 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)
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
 // benchmarkBuf is a read buffer we can reset
 type benchmarkBuf struct {
 	offset int
@@ -323,3 +340,27 @@
 		}
 	}
 }
+
+func BenchmarkDecodeInterfaceSlice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]interface{}, 1000)
+	for i := range a {
+		a[i] = "now is the time"
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		b.Fatal(err)
+	}
+	x := make([]interface{}, 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)
+		}
+	}
+}