encoding/json: speed up decoding

Don't make copies of keys while decoding, and don't use the
expensive strings.EqualFold when it's not necessary. Instead,
note in the existing field cache what algorithm to use to
check fold equality... most keys are just ASCII letters.

benchmark               old ns/op    new ns/op    delta
BenchmarkCodeDecoder    137074314    103974418  -24.15%

benchmark                old MB/s     new MB/s  speedup
BenchmarkCodeDecoder        14.16        18.66    1.32x

Update #6496

R=golang-dev, rsc, adg, r, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/13894045
This commit is contained in:
Brad Fitzpatrick 2013-12-18 07:30:21 -08:00
parent 5334b73d5d
commit 626da8d737
4 changed files with 282 additions and 8 deletions

View file

@ -8,6 +8,7 @@
package json
import (
"bytes"
"encoding"
"encoding/base64"
"errors"
@ -15,7 +16,6 @@ import (
"reflect"
"runtime"
"strconv"
"strings"
"unicode"
"unicode/utf16"
"unicode/utf8"
@ -500,11 +500,11 @@ func (d *decodeState) object(v reflect.Value) {
d.error(errPhase)
}
// Read string key.
// Read key.
start := d.off - 1
op = d.scanWhile(scanContinue)
item := d.data[start : d.off-1]
key, ok := unquote(item)
key, ok := unquoteBytes(item)
if !ok {
d.error(errPhase)
}
@ -526,11 +526,11 @@ func (d *decodeState) object(v reflect.Value) {
fields := cachedTypeFields(v.Type())
for i := range fields {
ff := &fields[i]
if ff.name == key {
if bytes.Equal(ff.nameBytes, key) {
f = ff
break
}
if f == nil && strings.EqualFold(ff.name, key) {
if f == nil && ff.equalFold(ff.nameBytes, key) {
f = ff
}
}