Commit eea0f199 authored by Rick Arnold's avatar Rick Arnold Committed by Russ Cox

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
parent 5215bedf
...@@ -52,16 +52,34 @@ import ( ...@@ -52,16 +52,34 @@ import (
// an UnmarshalTypeError describing the earliest such error. // an UnmarshalTypeError describing the earliest such error.
// //
func Unmarshal(data []byte, v interface{}) error { func Unmarshal(data []byte, v interface{}) error {
d := new(decodeState).init(data)
// Quick check for well-formedness. // Quick check for well-formedness.
// Avoids filling out half a data structure // Avoids filling out half a data structure
// before discovering a JSON syntax error. // before discovering a JSON syntax error.
var d decodeState
err := checkValid(data, &d.scan) err := checkValid(data, &d.scan)
if err != nil { if err != nil {
return err 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) return d.unmarshal(v)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment