]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/gob: optimize decoding of []byte
authorJoe Tsai <joetsai@digital-static.net>
Fri, 27 Aug 2021 03:26:32 +0000 (20:26 -0700)
committerJoe Tsai <joetsai@digital-static.net>
Fri, 27 Aug 2021 08:01:41 +0000 (08:01 +0000)
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>
src/encoding/gob/decode.go
src/encoding/gob/timing_test.go

index d2f6c749b1b6065693cb44940d89e91775f17805..4ef9ef7243ed578dff70f241626b58c606a420bf 100644 (file)
@@ -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)
index 3478bd247ed8562c0a0336ca73bd55edc97dd9ad..ceb21c4107b0a8b3e4b69982b06b3c139ea28b5a 100644 (file)
@@ -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 {