From 11ab865d6f42bcbfbe67219bd591518a1e1e8faf Mon Sep 17 00:00:00 2001 From: Filip Gruszczyński Date: Thu, 30 Mar 2017 19:09:56 -0700 Subject: encoding/gob: speedup decoding of maps by zeroing values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of allocating a new reflect.Value object on every loop we zero it. DecodeComplex128Slice-8 13.1µs ± 7% 13.2µs ± 8% ~ (p=0.347 n=18+19) DecodeFloat64Slice-8 8.13µs ± 5% 8.00µs ± 3% ~ (p=0.168 n=20+19) DecodeInt32Slice-8 8.27µs ± 5% 8.08µs ± 5% -2.27% (p=0.001 n=19+18) DecodeStringSlice-8 17.9µs ±12% 17.8µs ±11% ~ (p=0.989 n=20+19) DecodeInterfaceSlice-8 163µs ±10% 159µs ± 4% ~ (p=0.057 n=19+19) DecodeMap-8 220µs ± 2% 183µs ± 1% -17.07% (p=0.000 n=19+18) Updates #19525 Change-Id: I27f8edd4761787f6b9928d34cefa08a34a6e25b2 Reviewed-on: https://go-review.googlesource.com/39203 Reviewed-by: Brad Fitzpatrick Reviewed-by: Rob Pike Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/encoding/gob/codec_test.go | 27 +++++++++++++++++++++++++-- src/encoding/gob/decode.go | 10 ++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/encoding/gob/codec_test.go b/src/encoding/gob/codec_test.go index 387d58229c..eb9f306bcf 100644 --- a/src/encoding/gob/codec_test.go +++ b/src/encoding/gob/codec_test.go @@ -548,12 +548,14 @@ func TestEndToEnd(t *testing.T) { X float64 Z *int } - s1 := "string1" - s2 := "string2" type T1 struct { A, B, C int M map[string]*float64 M2 map[int]T3 + Mstring map[string]string + Mintptr map[int]*int + Mcomp map[complex128]complex128 + Marr map[[2]string][2]*float64 EmptyMap map[string]int // to check that we receive a non-nil map. N *[3]float64 Strs *[2]string @@ -565,14 +567,35 @@ func TestEndToEnd(t *testing.T) { } pi := 3.14159 e := 2.71828 + two := 2.0 meaning := 42 fingers := 5 + s1 := "string1" + s2 := "string2" + var comp1 complex128 = complex(1.0, 1.0) + var comp2 complex128 = complex(1.0, 1.0) + var arr1 [2]string + arr1[0] = s1 + arr1[1] = s2 + var arr2 [2]string + arr2[0] = s2 + arr2[1] = s1 + var floatArr1 [2]*float64 + floatArr1[0] = &pi + floatArr1[1] = &e + var floatArr2 [2]*float64 + floatArr2[0] = &e + floatArr2[1] = &two t1 := &T1{ A: 17, B: 18, C: -5, M: map[string]*float64{"pi": &pi, "e": &e}, M2: map[int]T3{4: T3{X: pi, Z: &meaning}, 10: T3{X: e, Z: &fingers}}, + Mstring: map[string]string{"pi": "3.14", "e": "2.71"}, + Mintptr: map[int]*int{meaning: &fingers, fingers: &meaning}, + Mcomp: map[complex128]complex128{comp1: comp2, comp2: comp1}, + Marr: map[[2]string][2]*float64{arr1: floatArr1, arr2: floatArr2}, EmptyMap: make(map[string]int), N: &[3]float64{1.5, 2.5, 3.5}, Strs: &[2]string{s1, s2}, diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go index 879d6d2b77..8dece42e90 100644 --- a/src/encoding/gob/decode.go +++ b/src/encoding/gob/decode.go @@ -565,10 +565,16 @@ func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, value refl elemIsPtr := mtyp.Elem().Kind() == reflect.Ptr keyInstr := &decInstr{keyOp, 0, nil, ovfl} elemInstr := &decInstr{elemOp, 0, nil, ovfl} + keyP := reflect.New(mtyp.Key()) + keyZ := reflect.Zero(mtyp.Key()) + elemP := reflect.New(mtyp.Elem()) + elemZ := reflect.Zero(mtyp.Elem()) for i := 0; i < n; i++ { - key := decodeIntoValue(state, keyOp, keyIsPtr, allocValue(mtyp.Key()), keyInstr) - elem := decodeIntoValue(state, elemOp, elemIsPtr, allocValue(mtyp.Elem()), elemInstr) + key := decodeIntoValue(state, keyOp, keyIsPtr, keyP.Elem(), keyInstr) + elem := decodeIntoValue(state, elemOp, elemIsPtr, elemP.Elem(), elemInstr) value.SetMapIndex(key, elem) + keyP.Elem().Set(keyZ) + elemP.Elem().Set(elemZ) } } -- cgit v1.2.3-54-g00ecf