1
0
mirror of https://github.com/golang/go synced 2024-11-18 15:44:41 -07:00

encoding/json: improve performance of Unmarshal on primitive types

Attempt 2. The first fix was much faster but ignored syntax errors.

benchmark                      old ns/op    new ns/op    delta
BenchmarkCodeEncoder            74993543     72982390   -2.68%
BenchmarkCodeMarshal            77811181     75610637   -2.83%
BenchmarkCodeDecoder           213337123    190144982  -10.87%
BenchmarkCodeUnmarshal         212180972    190394852  -10.27%
BenchmarkCodeUnmarshalReuse    202113428    182106660   -9.90%
BenchmarkUnmarshalString            1343          919  -31.57%
BenchmarkUnmarshalFloat64           1149          908  -20.97%
BenchmarkUnmarshalInt64              967          778  -19.54%
BenchmarkSkipValue              28851581     28414125   -1.52%

benchmark                       old MB/s     new MB/s  speedup
BenchmarkCodeEncoder               25.88        26.59    1.03x
BenchmarkCodeMarshal               24.94        25.66    1.03x
BenchmarkCodeDecoder                9.10        10.21    1.12x
BenchmarkCodeUnmarshal              9.15        10.19    1.11x
BenchmarkSkipValue                 69.05        70.11    1.02x

Fixes #3949.

R=rsc
CC=golang-dev
https://golang.org/cl/7231058
This commit is contained in:
Rick Arnold 2013-01-30 17:53:48 -08:00 committed by Russ Cox
parent 5215bedf49
commit eea0f19990

View File

@ -52,16 +52,34 @@ import (
// an UnmarshalTypeError describing the earliest such error.
//
func Unmarshal(data []byte, v interface{}) error {
d := new(decodeState).init(data)
// Quick check for well-formedness.
// Avoids filling out half a data structure
// before discovering a JSON syntax error.
var d decodeState
err := checkValid(data, &d.scan)
if err != nil {
return err
}
// skip heavy processing for primitive values
var first byte
var i int
for i, first = range data {
if first > ' ' || !isSpace(rune(first)) {
break
}
}
if first != '{' && first != '[' {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d.literalStore(data[i:], rv.Elem(), false)
return d.savedError
}
d.init(data)
return d.unmarshal(v)
}