Skip to content

Commit 67f7e16

Browse files
committed
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>
1 parent 2c60a99 commit 67f7e16

File tree

2 files changed

+9
-1
lines changed

2 files changed

+9
-1
lines changed

src/encoding/gob/decode.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) {
376376
if value.Cap() < n {
377377
value.Set(reflect.MakeSlice(value.Type(), n, n))
378378
} else {
379-
value.Set(value.Slice(0, n))
379+
value.SetLen(n)
380380
}
381381
if _, err := state.b.Read(value.Bytes()); err != nil {
382382
errorf("error decoding []byte: %s", err)

src/encoding/gob/timing_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,14 @@ func BenchmarkDecodeStringSlice(b *testing.B) {
280280
benchmarkDecodeSlice(b, a)
281281
}
282282

283+
func BenchmarkDecodeBytesSlice(b *testing.B) {
284+
a := make([][]byte, 1000)
285+
for i := range a {
286+
a[i] = []byte("now is the time")
287+
}
288+
benchmarkDecodeSlice(b, a)
289+
}
290+
283291
func BenchmarkDecodeInterfaceSlice(b *testing.B) {
284292
a := make([]interface{}, 1000)
285293
for i := range a {

0 commit comments

Comments
 (0)