]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/gob: use MakeMapWithSize when decoding map
authorFilip Gruszczyński <gruszczy@gmail.com>
Sun, 9 Apr 2017 17:44:39 +0000 (10:44 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 3 May 2017 02:43:40 +0000 (02:43 +0000)
This allows to pre-allocate the final size of the hashmap and avoid
re-allocating as we insert entries. Furthermore for the current
implementation of the hashmap it allows avoiding several rounds of
evacuating hashmap entries after each re-allocation.

DecodeComplex128Slice-8  51.9µs ± 1%  51.9µs ± 2%     ~     (p=0.797 n=30+29)
DecodeFloat64Slice-8     31.5µs ± 2%  31.6µs ± 2%     ~     (p=0.050 n=28+28)
DecodeInt32Slice-8       32.0µs ± 2%  31.9µs ± 3%     ~     (p=0.666 n=29+28)
DecodeStringSlice-8      57.7µs ± 2%  57.8µs ± 3%     ~     (p=0.780 n=27+30)
DecodeInterfaceSlice-8    498µs ± 2%   495µs ± 2%     ~     (p=0.070 n=28+29)
DecodeMap-8               300µs ± 2%   230µs ± 5%  -23.31%  (p=0.000 n=27+27)

Updates #19525

Change-Id: Ia7233da49f05bae7a86c064d9ecebca966f5f2f7
Reviewed-on: https://go-review.googlesource.com/40113
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/encoding/gob/decode.go
src/encoding/gob/timing_test.go

index 013f71ccdb7ef03e241a724110e5716d9ac10062..879d6d2b77d1bf104336df85c7028416de7bec4a 100644 (file)
@@ -557,11 +557,10 @@ func decodeIntoValue(state *decoderState, op decOp, isPtr bool, value reflect.Va
 // Because the internals of maps are not visible to us, we must
 // use reflection rather than pointer magic.
 func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, value reflect.Value, keyOp, elemOp decOp, ovfl error) {
+       n := int(state.decodeUint())
        if value.IsNil() {
-               // Allocate map.
-               value.Set(reflect.MakeMap(mtyp))
+               value.Set(reflect.MakeMapWithSize(mtyp, n))
        }
-       n := int(state.decodeUint())
        keyIsPtr := mtyp.Key().Kind() == reflect.Ptr
        elemIsPtr := mtyp.Elem().Kind() == reflect.Ptr
        keyInstr := &decInstr{keyOp, 0, nil, ovfl}
index 2a503ebfc505fd4bef4c2420282354cc1345ed20..3478bd247ed8562c0a0336ca73bd55edc97dd9ad 100644 (file)
@@ -289,7 +289,7 @@ func BenchmarkDecodeInterfaceSlice(b *testing.B) {
 }
 
 func BenchmarkDecodeMap(b *testing.B) {
-       count := 10000
+       count := 1000
        m := make(map[int]int, count)
        for i := 0; i < count; i++ {
                m[i] = i
@@ -303,7 +303,7 @@ func BenchmarkDecodeMap(b *testing.B) {
        bbuf := benchmarkBuf{data: buf.Bytes()}
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
-               rm := make(map[int]int, 0)
+               var rm map[int]int
                bbuf.reset()
                dec := NewDecoder(&bbuf)
                err := dec.Decode(&rm)