mirror of
https://github.com/golang/go
synced 2024-11-20 10:44:41 -07:00
encoding/json: improve performance of Unmarshal on primitive types
Skip most of the scanning and parsing logic for simple (non-object/array) JSON values. benchmark old ns/op new ns/op delta BenchmarkUnmarshalInt 948 436 -54.01% BenchmarkUnmarshalUint 930 427 -54.09% BenchmarkUnmarshalString 1407 715 -49.18% BenchmarkUnmarshalFloat 1114 536 -51.89% BenchmarkUnmarshalBool 759 266 -64.95% BenchmarkUnmarshalStruct 8165 8181 +0.20% No significant effects on the go1 benchmarks: benchmark old ns/op new ns/op delta BenchmarkBinaryTree17 9647362752 9596196417 -0.53% BenchmarkFannkuch11 5623613048 5518694872 -1.87% BenchmarkGobDecode 32944041 33165434 +0.67% BenchmarkGobEncode 21237482 21080554 -0.74% BenchmarkGzip 750955920 749861980 -0.15% BenchmarkGunzip 197369742 197886192 +0.26% BenchmarkJSONEncode 79274091 78891137 -0.48% BenchmarkJSONDecode 180257802 175280358 -2.76% BenchmarkMandelbrot200 7396666 7388266 -0.11% BenchmarkParse 11446460 11386550 -0.52% BenchmarkRevcomp 1605152523 1599512029 -0.35% BenchmarkTemplate 204538247 207765574 +1.58% benchmark old MB/s new MB/s speedup BenchmarkGobDecode 23.30 23.14 0.99x BenchmarkGobEncode 36.14 36.41 1.01x BenchmarkGzip 25.84 25.88 1.00x BenchmarkGunzip 98.32 98.06 1.00x BenchmarkJSONEncode 24.48 24.60 1.00x BenchmarkJSONDecode 10.76 11.07 1.03x BenchmarkParse 5.06 5.09 1.01x BenchmarkRevcomp 158.34 158.90 1.00x BenchmarkTemplate 9.49 9.34 0.98x Fixes #3949. R=golang-dev, dave, bradfitz, timo CC=golang-dev https://golang.org/cl/7068043
This commit is contained in:
parent
810e439859
commit
60abc6b577
@ -52,6 +52,25 @@ import (
|
||||
// an UnmarshalTypeError describing the earliest such error.
|
||||
//
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
|
||||
// skip heavy processing for primitive values
|
||||
var first byte
|
||||
var i int
|
||||
for i, first = range data {
|
||||
if !isSpace(rune(first)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if first != '{' && first != '[' {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr || rv.IsNil() {
|
||||
return &InvalidUnmarshalError{reflect.TypeOf(v)}
|
||||
}
|
||||
var d decodeState
|
||||
d.literalStore(data[i:], rv.Elem(), false)
|
||||
return d.savedError
|
||||
}
|
||||
|
||||
d := new(decodeState).init(data)
|
||||
|
||||
// Quick check for well-formedness.
|
||||
|
@ -205,6 +205,13 @@ var unmarshalTests = []unmarshalTest{
|
||||
{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64},
|
||||
{in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsNumber, useNumber: true},
|
||||
|
||||
// raw values with whitespace
|
||||
{in: "\n true ", ptr: new(bool), out: true},
|
||||
{in: "\t 1 ", ptr: new(int), out: 1},
|
||||
{in: "\r 1.2 ", ptr: new(float64), out: 1.2},
|
||||
{in: "\t -5 \n", ptr: new(int16), out: int16(-5)},
|
||||
{in: "\t \"a\\u1234\" \n", ptr: new(string), out: "a\u1234"},
|
||||
|
||||
// Z has a "-" tag.
|
||||
{in: `{"Y": 1, "Z": 2}`, ptr: new(T), out: T{Y: 1}},
|
||||
|
||||
@ -217,6 +224,16 @@ var unmarshalTests = []unmarshalTest{
|
||||
{in: `[1, 2, 3+]`, err: &SyntaxError{"invalid character '+' after array element", 9}},
|
||||
{in: `{"X":12x}`, err: &SyntaxError{"invalid character 'x' after object key:value pair", 8}, useNumber: true},
|
||||
|
||||
// raw value errors
|
||||
{in: "\x01 42", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
|
||||
{in: " 42 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 5}},
|
||||
{in: "\x01 true", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
|
||||
{in: " false \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 8}},
|
||||
{in: "\x01 1.2", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
|
||||
{in: " 3.4 \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 6}},
|
||||
{in: "\x01 \"string\"", err: &SyntaxError{"invalid character '\\x01' looking for beginning of value", 1}},
|
||||
{in: " \"string\" \x01", err: &SyntaxError{"invalid character '\\x01' after top-level value", 11}},
|
||||
|
||||
// array tests
|
||||
{in: `[1, 2, 3]`, ptr: new([3]int), out: [3]int{1, 2, 3}},
|
||||
{in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
|
||||
|
Loading…
Reference in New Issue
Block a user