encoding/gob: optimize decoding of []byte

The reflect.Value.Slice method unfortunately allocates every time
since it needs to place the slice header on the heap.
This is silly since gob immediately stores the result back into slice.
Instead, use the reflect.Value.SetLen method.

DecodeBytesSlice  75.0µs ± 2%  35.2µs ± 6%  -53.02%

Change-Id: I3ca0529d01bf978f2b76e215f52d369f458951ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/345572
Trust: Joe Tsai <joetsai@digital-static.net>
Run-TryBot: Joe Tsai <joetsai@digital-static.net>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
index d2f6c74..4ef9ef7 100644
--- a/src/encoding/gob/decode.go
+++ b/src/encoding/gob/decode.go
@@ -376,7 +376,7 @@
 	if value.Cap() < n {
 		value.Set(reflect.MakeSlice(value.Type(), n, n))
 	} else {
-		value.Set(value.Slice(0, n))
+		value.SetLen(n)
 	}
 	if _, err := state.b.Read(value.Bytes()); err != nil {
 		errorf("error decoding []byte: %s", err)
diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go
index 3478bd2..ceb21c4 100644
--- a/src/encoding/gob/timing_test.go
+++ b/src/encoding/gob/timing_test.go
@@ -280,6 +280,14 @@
 	benchmarkDecodeSlice(b, a)
 }
 
+func BenchmarkDecodeBytesSlice(b *testing.B) {
+	a := make([][]byte, 1000)
+	for i := range a {
+		a[i] = []byte("now is the time")
+	}
+	benchmarkDecodeSlice(b, a)
+}
+
 func BenchmarkDecodeInterfaceSlice(b *testing.B) {
 	a := make([]interface{}, 1000)
 	for i := range a {