]> Cypherpunks.ru repositories - gostls13.git/commitdiff
encoding/json: optimize Unmarshal for maps
authorkorzhao <korzhao95@gmail.com>
Sun, 30 Jul 2023 07:02:15 +0000 (15:02 +0800)
committerGopher Robot <gobot@golang.org>
Mon, 31 Jul 2023 18:34:45 +0000 (18:34 +0000)
benchmark                    old ns/op     new ns/op     delta
BenchmarkUnmarshalMap-10     218           172           -21.28%

benchmark                    old allocs     new allocs     delta
BenchmarkUnmarshalMap-10     15             12             -20.00%

benchmark                    old bytes     new bytes     delta
BenchmarkUnmarshalMap-10     328           256           -21.95%

Change-Id: Ie20ab62731c752eb0040c6d1591fedd7d12b1e0c
Reviewed-on: https://go-review.googlesource.com/c/go/+/514100
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>

src/encoding/json/bench_test.go
src/encoding/json/decode.go

index d3af0dc0ed62bd27e3344fb6ae228dc29fb69deb..bafccdf1935e2f5fc5c2738e71cf73c7f068d5ef 100644 (file)
@@ -385,6 +385,19 @@ func BenchmarkUnmarshalInt64(b *testing.B) {
        })
 }
 
+func BenchmarkUnmarshalMap(b *testing.B) {
+       b.ReportAllocs()
+       data := []byte(`{"key1":"value1","key2":"value2","key3":"value3"}`)
+       b.RunParallel(func(pb *testing.PB) {
+               x := make(map[string]string, 3)
+               for pb.Next() {
+                       if err := Unmarshal(data, &x); err != nil {
+                               b.Fatal("Unmarshal:", err)
+                       }
+               }
+       })
+}
+
 func BenchmarkIssue10335(b *testing.B) {
        b.ReportAllocs()
        j := []byte(`{"a":{ }}`)
index 53470d8c88e4ab1bdb9da48f76b63590da4e0177..2142816d889cbd2dc78d31780eca0432d16fc928 100644 (file)
@@ -762,17 +762,17 @@ func (d *decodeState) object(v reflect.Value) error {
                if v.Kind() == reflect.Map {
                        kt := t.Key()
                        var kv reflect.Value
-                       switch {
-                       case reflect.PointerTo(kt).Implements(textUnmarshalerType):
+                       if reflect.PointerTo(kt).Implements(textUnmarshalerType) {
                                kv = reflect.New(kt)
                                if err := d.literalStore(item, kv, true); err != nil {
                                        return err
                                }
                                kv = kv.Elem()
-                       case kt.Kind() == reflect.String:
-                               kv = reflect.ValueOf(key).Convert(kt)
-                       default:
+                       } else {
                                switch kt.Kind() {
+                               case reflect.String:
+                                       kv = reflect.New(kt).Elem()
+                                       kv.SetString(string(key))
                                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
                                        s := string(key)
                                        n, err := strconv.ParseInt(s, 10, 64)
@@ -780,7 +780,8 @@ func (d *decodeState) object(v reflect.Value) error {
                                                d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
                                                break
                                        }
-                                       kv = reflect.ValueOf(n).Convert(kt)
+                                       kv = reflect.New(kt).Elem()
+                                       kv.SetInt(n)
                                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
                                        s := string(key)
                                        n, err := strconv.ParseUint(s, 10, 64)
@@ -788,7 +789,8 @@ func (d *decodeState) object(v reflect.Value) error {
                                                d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
                                                break
                                        }
-                                       kv = reflect.ValueOf(n).Convert(kt)
+                                       kv = reflect.New(kt).Elem()
+                                       kv.SetUint(n)
                                default:
                                        panic("json: Unexpected key type") // should never occur
                                }