diff options
| author | Brad Fitzpatrick <bradfitz@golang.org> | 2011-12-15 11:21:21 -0800 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2011-12-15 11:21:21 -0800 |
| commit | 29264c6f4f341586b733e2c5b165ca627b6050d8 (patch) | |
| tree | b8e068d54ec1828b5e2f1901e4b53563434d0e8c /src/pkg/encoding/json/encode.go | |
| parent | 143f3b38f5fe48d33bff8f76728739694b3e060f (diff) | |
| download | go-29264c6f4f341586b733e2c5b165ca627b6050d8.tar.xz | |
json: use strconv.Append variants to avoid allocations in encoding
Before/after, best of 3:
json.BenchmarkCodeEncoder 10 183495300 ns/op 10.58 MB/s
->
json.BenchmarkCodeEncoder 10 133025100 ns/op 14.59 MB/s
But don't get too excited about this. These benchmarks, while
stable at any point of time, fluctuate wildly with any line of
code added or removed anywhere in the path due to stack splitting
issues.
It's currently much faster, though, and this is the API that
doesn't allocate so should always be faster in theory.
R=golang-dev, dsymonds, rsc, r, gri
CC=golang-dev
https://golang.org/cl/5411052
Diffstat (limited to 'src/pkg/encoding/json/encode.go')
| -rw-r--r-- | src/pkg/encoding/json/encode.go | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/src/pkg/encoding/json/encode.go b/src/pkg/encoding/json/encode.go index ff8e80c091..3d2f4fc316 100644 --- a/src/pkg/encoding/json/encode.go +++ b/src/pkg/encoding/json/encode.go @@ -197,6 +197,7 @@ var hex = "0123456789abcdef" // An encodeState encodes JSON into a bytes.Buffer. type encodeState struct { bytes.Buffer // accumulated output + scratch [64]byte } func (e *encodeState) marshal(v interface{}) (err error) { @@ -275,14 +276,26 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) { } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - writeString(e, strconv.FormatInt(v.Int(), 10)) - + b := strconv.AppendInt(e.scratch[:0], v.Int(), 10) + if quoted { + writeString(e, string(b)) + } else { + e.Write(b) + } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - writeString(e, strconv.FormatUint(v.Uint(), 10)) - + b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10) + if quoted { + writeString(e, string(b)) + } else { + e.Write(b) + } case reflect.Float32, reflect.Float64: - writeString(e, strconv.FormatFloat(v.Float(), 'g', -1, v.Type().Bits())) - + b := strconv.AppendFloat(e.scratch[:0], v.Float(), 'g', -1, v.Type().Bits()) + if quoted { + writeString(e, string(b)) + } else { + e.Write(b) + } case reflect.String: if quoted { sb, err := Marshal(v.String()) |
