diff options
author | Joe Tsai <joetsai@digital-static.net> | 2021-08-26 20:26:32 -0700 |
---|---|---|
committer | Joe Tsai <joetsai@digital-static.net> | 2021-08-27 08:01:41 +0000 |
commit | 67f7e16bcce0a3e68bf92e233ea16c8a9d2ac07a (patch) | |
tree | b0f76651404446665969e3d7ad6ccf8c1234111f | |
parent | 2c60a99f723e779a39664b5f12cb41878fd4a700 (diff) | |
download | go-67f7e16bcce0a3e68bf92e233ea16c8a9d2ac07a.tar.gz go-67f7e16bcce0a3e68bf92e233ea16c8a9d2ac07a.zip |
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>
-rw-r--r-- | src/encoding/gob/decode.go | 2 | ||||
-rw-r--r-- | src/encoding/gob/timing_test.go | 8 |
2 files changed, 9 insertions, 1 deletions
diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go index d2f6c749b1..4ef9ef7243 100644 --- a/src/encoding/gob/decode.go +++ b/src/encoding/gob/decode.go @@ -376,7 +376,7 @@ func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) { 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 3478bd247e..ceb21c4107 100644 --- a/src/encoding/gob/timing_test.go +++ b/src/encoding/gob/timing_test.go @@ -280,6 +280,14 @@ func BenchmarkDecodeStringSlice(b *testing.B) { 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 { |