aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2021-08-26 20:26:32 -0700
committerJoe Tsai <joetsai@digital-static.net>2021-08-27 08:01:41 +0000
commit67f7e16bcce0a3e68bf92e233ea16c8a9d2ac07a (patch)
treeb0f76651404446665969e3d7ad6ccf8c1234111f
parent2c60a99f723e779a39664b5f12cb41878fd4a700 (diff)
downloadgo-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.go2
-rw-r--r--src/encoding/gob/timing_test.go8
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 {