aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json/bench_test.go
AgeCommit message (Collapse)Author
2026-02-02encoding/json: use pooled encoder in Encoder.EncodeJoe Tsai
Due to the lack of MarshalWrite in the v1 API, it is unfortunately common to see: json.NewEncoder(out).Encode(in) where a single-use Encoder is constructed and thrown away. This performed acceptably in v1 since every call to Encode used a globally pooled encoder resource. Prior to this change, the v1-in-v2 implementation relied on a bytes.Buffer cached only for the lifetime of the Encoder object itself. Thus, a single-use Encoder does not benefit. Modify the wrapper implementation to use the internal pooled encoder from v2 and use the intermediate buffer to write directly to the output io.Writer. We assume that the user-provided io.Writer never leaks the buffer, but this assumption was already held in the v1 implementation. We are not increasing the surface area of data corruption risk. Performance of v1 to v1-in-v2 (before the pool fix): name old time/op new time/op delta NewEncoderEncode-32 30.2ms ± 4% 28.3ms ± 9% -6.19% (p=0.002 n=9+10) name old alloc/op new alloc/op delta NewEncoderEncode-32 7.64MB ± 0% 28.37MB ± 0% +271.23% (p=0.000 n=10+10) name old allocs/op new allocs/op delta NewEncoderEncode-32 200k ± 0% 100k ± 0% -49.99% (p=0.000 n=9+10) Interestingly, v1-in-2 is slightly faster, but the amount of allocated memory is massive. Performance of v1 to v1-in-v2 (after the pool fix): name old time/op new time/op delta NewEncoderEncode-32 30.2ms ± 4% 24.0ms ± 7% -20.36% (p=0.000 n=9+10) name old alloc/op new alloc/op delta NewEncoderEncode-32 7.64MB ± 0% 4.09MB ± 3% -46.52% (p=0.000 n=10+10) name old allocs/op new allocs/op delta NewEncoderEncode-32 200k ± 0% 100k ± 0% -50.00% (p=0.000 n=9+9) Now, the v1-in-v2 implementation is better than v1 on all metrics. Fixes #75026 Change-Id: I50c975b1d5b8da806e46bc627966b0a39c1817eb Reviewed-on: https://go-review.googlesource.com/c/go/+/740660 Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-06-24encoding/json: use zstd compressed testdataJoe Tsai
There is a non-public zstd decoder in the stdlib (CL 473356) and also zstd compressed testdata already present. Delete testdata/code.json.gz and instead use internal/jsontest/testdata/golang_source.json.zst, which has exactly the same content: $ cat internal/jsontest/testdata/golang_source.json.zst | zstd -d | sha1sum 3f70b6fd429f4aba3e8e1c3e5a294c8f2e219a6e - $ cat testdata/code.json.gz | zstd -d | sha1sum 3f70b6fd429f4aba3e8e1c3e5a294c8f2e219a6e - This will reduce the size of the final Go release by 118KB. Updates #71845 Change-Id: I6da2df27bd260befc0a44c6bc0255365be0a5b0f Reviewed-on: https://go-review.googlesource.com/c/go/+/525516 Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> TryBot-Bypass: Damien Neil <dneil@google.com>
2025-04-18encoding/json: add json/v2 with GOEXPERIMENT=jsonv2 guardDamien Neil
This imports the proposed new v2 JSON API implemented in github.com/go-json-experiment/json as of commit d3c622f1b874954c355e60c8e6b6baa5f60d2fed. When GOEXPERIMENT=jsonv2 is set, the encoding/json/v2 and encoding/jsontext packages are visible, the encoding/json package is implemented in terms of encoding/json/v2, and the encoding/json package include various additional APIs. (See #71497 for details.) When GOEXPERIMENT=jsonv2 is not set, the new API is not present and the encoding/json package is unchanged. The experimental API is not bound by the Go compatibility promise and is expected to evolve as updates are made to the json/v2 proposal. The contents of encoding/json/internal/jsontest/testdata are compressed with zstd v1.5.7 with the -19 option. Fixes #71845 For #71497 Change-Id: Ib8c94e5f0586b6aaa22833190b41cf6ef59f4f01 Reviewed-on: https://go-review.googlesource.com/c/go/+/665796 Auto-Submit: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2024-04-02encoding/json: prevent duplicate slicebytetostringShengyu Zhang
When storing literal to JSON number v, if s is valid number, the slicebytetostring operation will be performed twice. In fact, the operation is unavoidable on any code path, so just perform it at the very beginning. This is not a big optimization, but better than nothing: $ ../bin/go test ./encoding/json/ -bench UnmarshalNumber -run NOTEST -benchtime 10000000x -count 16 > old.txt $ ../bin/go test ./encoding/json/ -bench UnmarshalNumber -run NOTEST -benchtime 10000000x -count 16 > new.txt $ benchstat old.txt new.txt │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ UnmarshalNumber-8 234.5n ± 3% 228.2n ± 4% -2.67% (p=0.033 n=16) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ UnmarshalNumber-8 168.0 ± 0% 168.0 ± 0% ~ (p=1.000 n=16) ¹ ¹ all samples are equal │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ UnmarshalNumber-8 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=16) ¹ ¹ all samples are equal Change-Id: I1dfdb1ed0883e385f753b2046b7f047c792aa4e3 GitHub-Last-Rev: d236dd7265f110dbb6e0b9b0a824aab9ba7c36be GitHub-Pull-Request: golang/go#61242 Reviewed-on: https://go-review.googlesource.com/c/go/+/508556 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: qiulaidongfeng <2645477756@qq.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
2023-08-25encoding/json: modernize testsJoe Tsai
There are no changes to what is being tested. No test cases were removed or added. Changes made: * Use a local implementation of test case position marking. See #52751. * Use consistent names for all test tables and variables. * Generally speaking, follow modern Go style guide for tests. * Move global tables local to the test function if possible. * Make every table entry run in a distinct testing.T.Run. The purpose of this change is to make it easier to perform v1-to-v2 development where we want v2 to support close to bug-for-bug compatibility when running in v1 mode. Annotating each test case with the location of the test data makes it easier to jump directly to the test data itself and understand why this particular case is failing. Having every test case run in its own t.Run makes it easier to isolate a particular failing test and work on fixing the code until that test case starts to pass again. Unfortunately, many tests are annotated with an empty name. An empty name is better than nothing, since the testing framework auto assigns a numeric ID for duplicate names. It is not worth the trouble to give descriptive names to each of the thousands of test cases. Change-Id: I43905f35249b3d77dfca234b9c7808d40e225de8 Reviewed-on: https://go-review.googlesource.com/c/go/+/522880 Auto-Submit: Joseph Tsai <joetsai@digital-static.net> Run-TryBot: Joseph Tsai <joetsai@digital-static.net> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Damien Neil <dneil@google.com>
2023-08-25encoding/json: optimize Marshal for mapskorzhao
Optimize marshaling of maps by using slices.SortFunc. This drops an unnecessary field from reflectWithString, which also reduces the cost of each swap operation. benchmark old ns/op new ns/op delta BenchmarkMarshalMap-10 228 139 -39.24% benchmark old allocs new allocs delta BenchmarkMarshalMap-10 11 8 -27.27% benchmark old bytes new bytes delta BenchmarkMarshalMap-10 432 232 -46.30% Change-Id: Ic2ba7a1590863c7536305c6f6536372b26ec9b0c Reviewed-on: https://go-review.googlesource.com/c/go/+/515176 Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: qiulaidongfeng <2645477756@qq.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2023-08-01encoding/json: use reflect.TypeFor for known typesIan Lance Taylor
For #60088 Change-Id: I2e471c76de62944b14472966b63f5778124b9b8b Reviewed-on: https://go-review.googlesource.com/c/go/+/514655 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@golang.org> Run-TryBot: Joseph Tsai <joetsai@digital-static.net> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
2023-07-31encoding/json: optimize Unmarshal for mapskorzhao
benchmark old ns/op new ns/op delta BenchmarkUnmarshalMap-10 218 172 -21.28% benchmark old allocs new allocs delta BenchmarkUnmarshalMap-10 15 12 -20.00% benchmark old bytes new bytes delta BenchmarkUnmarshalMap-10 328 256 -21.95% Change-Id: Ie20ab62731c752eb0040c6d1591fedd7d12b1e0c Reviewed-on: https://go-review.googlesource.com/c/go/+/514100 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
2022-08-24encoding/json: move some misplaced benchmark tests to bench_test.goAndy Pan
Change-Id: I5987eed00ee825421abe62699a06e9b66499f35f Reviewed-on: https://go-review.googlesource.com/c/go/+/425016 Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Reviewed-by: David Chase <drchase@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2022-08-23encoding/json: give it a chance to put encodeState back in pool when error ↵Andy Pan
occurs name old time/op new time/op delta CodeEncoderError-10 688µs ± 8% 496µs ±15% -27.92% (p=0.000 n=10+9) CodeMarshalError-10 747µs ± 6% 546µs ± 4% -26.86% (p=0.000 n=10+10) MarshalBytesError/32-10 284µs ± 2% 273µs ± 1% -3.84% (p=0.000 n=10+10) MarshalBytesError/256-10 281µs ± 2% 278µs ± 4% ~ (p=0.053 n=9+10) MarshalBytesError/4096-10 290µs ± 1% 279µs ± 3% -3.52% (p=0.000 n=10+10) name old speed new speed delta CodeEncoderError-10 2.83GB/s ± 8% 3.84GB/s ±20% +36.03% (p=0.000 n=10+10) CodeMarshalError-10 2.60GB/s ± 5% 3.56GB/s ± 4% +36.61% (p=0.000 n=10+10) name old alloc/op new alloc/op delta CodeEncoderError-10 4.05MB ± 1% 0.00MB ± 1% -100.00% (p=0.000 n=10+9) CodeMarshalError-10 6.05MB ± 0% 1.99MB ± 1% -67.13% (p=0.000 n=10+10) MarshalBytesError/32-10 66.0kB ± 0% 0.2kB ± 0% -99.67% (p=0.000 n=9+8) MarshalBytesError/256-10 50.1kB ± 0% 0.9kB ± 0% -98.23% (p=0.000 n=9+9) MarshalBytesError/4096-10 87.4kB ± 0% 7.5kB ± 0% -91.47% (p=0.000 n=8+10) name old allocs/op new allocs/op delta CodeEncoderError-10 25.0 ± 0% 4.0 ± 0% -84.00% (p=0.000 n=9+10) CodeMarshalError-10 27.0 ± 0% 6.0 ± 0% -77.78% (p=0.000 n=10+10) MarshalBytesError/32-10 18.0 ± 0% 5.0 ± 0% -72.22% (p=0.000 n=10+10) MarshalBytesError/256-10 17.0 ± 0% 6.0 ± 0% -64.71% (p=0.000 n=10+10) MarshalBytesError/4096-10 16.0 ± 0% 6.0 ± 0% -62.50% (p=0.000 n=10+10) Change-Id: I48070bb05f55707251c694e40d2570403bbf61f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/423694 Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Run-TryBot: Ian Lance Taylor <iant@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
2021-12-13all: gofmt -w -r 'interface{} -> any' srcRuss Cox
And then revert the bootstrap cmd directories and certain testdata. And adjust tests as needed. Not reverting the changes in std that are bootstrapped, because some of those changes would appear in API docs, and we want to use any consistently. Instead, rewrite 'any' to 'interface{}' in cmd/dist for those directories when preparing the bootstrap copy. A few files changed as a result of running gofmt -w not because of interface{} -> any but because they hadn't been updated for the new //go:build lines. Fixes #49884. Change-Id: Ie8045cba995f65bd79c694ec77a1b3d1fe01bb09 Reviewed-on: https://go-review.googlesource.com/c/go/+/368254 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
2020-10-20all: update references to symbols moved from io/ioutil to ioRuss Cox
The old ioutil references are still valid, but update our code to reflect best practices and get used to the new locations. Code compiled with the bootstrap toolchain (cmd/asm, cmd/dist, cmd/compile, debug/elf) must remain Go 1.4-compatible and is excluded. Also excluded vendored code. For #41190. Change-Id: I6d86f2bf7bc37a9d904b6cee3fe0c7af6d94d5b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/263142 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
2019-10-27encoding/json: improve performance of CompactPhil Pearl
This change improves performance of Compact by using a sync.Pool to allow re-use of a scanner. This also has the side-effect of removing an allocation for each field that implements Marshaler when marshalling JSON. name old time/op new time/op delta EncodeMarshaler-8 118ns ± 2% 104ns ± 1% -12.21% (p=0.001 n=7+7) name old alloc/op new alloc/op delta EncodeMarshaler-8 100B ± 0% 36B ± 0% -64.00% (p=0.000 n=8+8) name old allocs/op new allocs/op delta EncodeMarshaler-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=8+8) Change-Id: Ic70c61a0a6354823da5220f5aad04b94c054f233 Reviewed-on: https://go-review.googlesource.com/c/go/+/200864 Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org>
2019-09-11encoding/json: fix and optimize marshal for quoted stringLucas Bremgartner
Since Go 1.2 every string can be marshaled to JSON without error even if it contains invalid UTF-8 byte sequences. Therefore there is no need to use Marshal again for the only reason of enclosing the string in double quotes. Not using Marshal here also removes the error check as there has not been a way for Marshal to fail anyway. name old time/op new time/op delta Issue34127-4 360ns ± 3% 200ns ± 3% -44.56% (p=0.008 n=5+5) name old alloc/op new alloc/op delta Issue34127-4 56.0B ± 0% 40.0B ± 0% -28.57% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Issue34127-4 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.008 n=5+5) Fixes #34154 Change-Id: Ib60dc11980f9b20d8bef2982de7168943d632263 GitHub-Last-Rev: 9b0ac1d4c5318b6bf9ed7930320f2bd755f9939c GitHub-Pull-Request: golang/go#34127 Reviewed-on: https://go-review.googlesource.com/c/go/+/193604 Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org>
2019-04-05encoding/json: use SetBytes in UnmarshalReuse benchmarkDaniel Martí
This was the only benchmark missing the SetBytes call, as spotted earlier by Bryan. It's not required to make the benchmark useful, but it can still be a good way to see how its speed is affected by the reduced allocations: name time/op CodeUnmarshal-8 12.1ms ± 1% CodeUnmarshalReuse-8 11.4ms ± 1% name speed CodeUnmarshal-8 161MB/s ± 1% CodeUnmarshalReuse-8 171MB/s ± 1% name alloc/op CodeUnmarshal-8 3.28MB ± 0% CodeUnmarshalReuse-8 1.94MB ± 0% name allocs/op CodeUnmarshal-8 92.7k ± 0% CodeUnmarshalReuse-8 77.6k ± 0% While at it, remove some unnecessary empty lines. Change-Id: Ib2bd92d5b3237b8f3092e8c6f863dab548fee2f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/170938 Run-TryBot: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2019-03-18encoding/json: fix performance regression in the decoderDaniel Martí
In golang.org/cl/145218, a feature was added where the JSON decoder would keep track of the entire path to a field when reporting an UnmarshalTypeError. However, we all failed to check if this affected the benchmarks - myself included, as a reviewer. Below are the numbers comparing the CL's parent with itself, once it was merged: name old time/op new time/op delta CodeDecoder-8 12.9ms ± 1% 28.2ms ± 2% +119.33% (p=0.002 n=6+6) name old speed new speed delta CodeDecoder-8 151MB/s ± 1% 69MB/s ± 3% -54.40% (p=0.002 n=6+6) name old alloc/op new alloc/op delta CodeDecoder-8 2.74MB ± 0% 109.39MB ± 0% +3891.83% (p=0.002 n=6+6) name old allocs/op new allocs/op delta CodeDecoder-8 77.5k ± 0% 168.5k ± 0% +117.30% (p=0.004 n=6+5) The reason why the decoder got twice as slow is because it now allocated ~40x as many objects, which puts a lot of pressure on the garbage collector. The reason is that the CL concatenated strings every time a nested field was decoded. In other words, practically every field generated garbage when decoded. This is hugely wasteful, especially considering that the vast majority of JSON decoding inputs won't return UnmarshalTypeError. Instead, use a stack of fields, and make sure to always use the same backing array, to ensure we only need to grow the slice to the maximum depth once. The original CL also introduced a bug. The field stack string wasn't reset to its original state when reaching "d.opcode == scanEndObject", so the last field in a decoded struct could leak. For example, an added test decodes a list of structs, and encoding/json before this CL would fail: got: cannot unmarshal string into Go struct field T.Ts.Y.Y.Y of type int want: cannot unmarshal string into Go struct field T.Ts.Y of type int To fix that, simply reset the stack after decoding every field, even if it's the last. Below is the original performance versus this CL. There's a tiny performance hit, probably due to the append for every decoded field, but at least we're back to the usual ~150MB/s. name old time/op new time/op delta CodeDecoder-8 12.9ms ± 1% 13.0ms ± 1% +1.25% (p=0.009 n=6+6) name old speed new speed delta CodeDecoder-8 151MB/s ± 1% 149MB/s ± 1% -1.24% (p=0.009 n=6+6) name old alloc/op new alloc/op delta CodeDecoder-8 2.74MB ± 0% 2.74MB ± 0% +0.00% (p=0.002 n=6+6) name old allocs/op new allocs/op delta CodeDecoder-8 77.5k ± 0% 77.5k ± 0% +0.00% (p=0.002 n=6+6) Finally, make all of these benchmarks report allocs by default. The decoder ones are pretty sensitive to generated garbage, so ReportAllocs would have made the performance regression more obvious. Change-Id: I67b50f86b2e72f55539429450c67bfb1a9464b67 Reviewed-on: https://go-review.googlesource.com/c/go/+/167978 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org>
2018-08-21encoding/json: remove alloc when encoding short byte slicesDaniel Martí
If the encoded bytes fit in the bootstrap array encodeState.scratch, use that instead of allocating a new byte slice. Also tweaked the Encoding vs Encoder heuristic to use the length of the encoded bytes, not the length of the input bytes. Encoding is used for allocations of up to 1024 bytes, as we measured 2048 to be the point where it no longer provides a noticeable advantage. Also added some benchmarks. Only the first case changes in behavior. name old time/op new time/op delta MarshalBytes/32-4 420ns ± 1% 383ns ± 1% -8.69% (p=0.002 n=6+6) MarshalBytes/256-4 913ns ± 1% 915ns ± 0% ~ (p=0.580 n=5+6) MarshalBytes/4096-4 7.72µs ± 0% 7.74µs ± 0% ~ (p=0.340 n=5+6) name old alloc/op new alloc/op delta MarshalBytes/32-4 112B ± 0% 64B ± 0% -42.86% (p=0.002 n=6+6) MarshalBytes/256-4 736B ± 0% 736B ± 0% ~ (all equal) MarshalBytes/4096-4 7.30kB ± 0% 7.30kB ± 0% ~ (all equal) name old allocs/op new allocs/op delta MarshalBytes/32-4 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.002 n=6+6) MarshalBytes/256-4 2.00 ± 0% 2.00 ± 0% ~ (all equal) MarshalBytes/4096-4 2.00 ± 0% 2.00 ± 0% ~ (all equal) Updates #5683. Change-Id: I5fa55c27bd7728338d770ae7c0756885ba9a5724 Reviewed-on: https://go-review.googlesource.com/122462 Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2018-03-03encoding/json: use sync.Map for field cacheJoe Tsai
The previous type cache is quadratic in time in the situation where new types are continually encountered. Now that it is possible to dynamically create new types with the reflect package, this can cause json to perform very poorly. Switch to sync.Map which does well when the cache has hit steady state, but also handles occasional updates in better than quadratic time. benchmark old ns/op new ns/op delta BenchmarkTypeFieldsCache/MissTypes1-8 14817 16202 +9.35% BenchmarkTypeFieldsCache/MissTypes10-8 70926 69144 -2.51% BenchmarkTypeFieldsCache/MissTypes100-8 976467 208973 -78.60% BenchmarkTypeFieldsCache/MissTypes1000-8 79520162 1750371 -97.80% BenchmarkTypeFieldsCache/MissTypes10000-8 6873625837 16847806 -99.75% BenchmarkTypeFieldsCache/HitTypes1000-8 7.51 8.80 +17.18% BenchmarkTypeFieldsCache/HitTypes10000-8 7.58 8.68 +14.51% The old implementation takes 12 minutes just to build a cache of size 1e5 due to the quadratic behavior. I did not bother benchmark sizes above that. Change-Id: I5e6facc1eb8e1b80e5ca285e4dd2cc8815618dad Reviewed-on: https://go-review.googlesource.com/76850 Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com> Reviewed-by: Bryan Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-11-22encoding/json: reduce allocations by Decoder for \uXXXXMichael Schurter
Manually convert hex escape sequence to rune instead of calling strconv.ParseUint. This inlines the unhex func from docs (and many other packages). name old time/op new time/op delta UnicodeDecoder-4 468ns ± 1% 402ns ± 1% -14.26% (p=0.000 n=10+10) name old speed new speed delta UnicodeDecoder-4 29.9MB/s ± 1% 34.8MB/s ± 1% +16.59% (p=0.000 n=10+10) name old alloc/op new alloc/op delta UnicodeDecoder-4 44.0B ± 0% 36.0B ± 0% -18.18% (p=0.000 n=10+10) name old allocs/op new allocs/op delta UnicodeDecoder-4 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=10+10) Fixes #20567 Change-Id: If350978d5bb98ff517485752184d02249f5d1f3a Reviewed-on: https://go-review.googlesource.com/44738 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-04-26encoding/json: parallelize most benchmarksBryan C. Mills
Don't bother with BenchmarkDecoderStream — it's doing something subtle with the input buffer that isn't easy to replicate in a parallel test. Results remain comparable with the non-parallel version with -cpu=1: benchmark old ns/op new ns/op delta BenchmarkCodeEncoder 22815832 21058729 -7.70% BenchmarkCodeEncoder-6 22190561 3579757 -83.87% BenchmarkCodeMarshal 25356621 25396429 +0.16% BenchmarkCodeMarshal-6 25359813 4944908 -80.50% BenchmarkCodeDecoder 94794556 88016360 -7.15% BenchmarkCodeDecoder-6 93795028 16726283 -82.17% BenchmarkDecoderStream 532 583 +9.59% BenchmarkDecoderStream-6 598 550 -8.03% BenchmarkCodeUnmarshal 97644168 89162504 -8.69% BenchmarkCodeUnmarshal-6 96615302 17036419 -82.37% BenchmarkCodeUnmarshalReuse 91747073 90298479 -1.58% BenchmarkCodeUnmarshalReuse-6 89397165 15518005 -82.64% BenchmarkUnmarshalString 808 843 +4.33% BenchmarkUnmarshalString-6 912 220 -75.88% BenchmarkUnmarshalFloat64 695 732 +5.32% BenchmarkUnmarshalFloat64-6 710 191 -73.10% BenchmarkUnmarshalInt64 635 640 +0.79% BenchmarkUnmarshalInt64-6 618 185 -70.06% BenchmarkIssue10335 916 947 +3.38% BenchmarkIssue10335-6 879 216 -75.43% BenchmarkNumberIsValid 34.7 34.3 -1.15% BenchmarkNumberIsValid-6 34.9 36.7 +5.16% BenchmarkNumberIsValidRegexp 1174 1121 -4.51% BenchmarkNumberIsValidRegexp-6 1134 1119 -1.32% BenchmarkSkipValue 20506938 20708060 +0.98% BenchmarkSkipValue-6 21627665 22375630 +3.46% BenchmarkEncoderEncode 690 726 +5.22% BenchmarkEncoderEncode-6 649 157 -75.81% benchmark old MB/s new MB/s speedup BenchmarkCodeEncoder 85.05 92.15 1.08x BenchmarkCodeEncoder-6 87.45 542.07 6.20x BenchmarkCodeMarshal 76.53 76.41 1.00x BenchmarkCodeMarshal-6 76.52 392.42 5.13x BenchmarkCodeDecoder 20.47 22.05 1.08x BenchmarkCodeDecoder-6 20.69 116.01 5.61x BenchmarkCodeUnmarshal 19.87 21.76 1.10x BenchmarkCodeUnmarshal-6 20.08 113.90 5.67x BenchmarkSkipValue 90.55 89.67 0.99x BenchmarkSkipValue-6 90.83 87.80 0.97x benchmark old allocs new allocs delta BenchmarkIssue10335 4 4 +0.00% BenchmarkIssue10335-6 4 4 +0.00% BenchmarkEncoderEncode 1 1 +0.00% BenchmarkEncoderEncode-6 1 1 +0.00% benchmark old bytes new bytes delta BenchmarkIssue10335 320 320 +0.00% BenchmarkIssue10335-6 320 320 +0.00% BenchmarkEncoderEncode 8 8 +0.00% BenchmarkEncoderEncode-6 8 8 +0.00% updates #18177 Change-Id: Ia4f5bf5ac0afbadb1705ed9f9e1b39dabba67b40 Reviewed-on: https://go-review.googlesource.com/36724 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-03-20encoding/json: reduce unmarshal mallocs for unmapped fieldsPascal S. de Kloe
JSON decoding performs poorly for unmapped and ignored fields. We noticed better performance when unmarshalling unused fields. The loss comes mostly from calls to scanner.error as described at #17914. benchmark old ns/op new ns/op delta BenchmarkIssue10335-8 431 408 -5.34% BenchmarkUnmapped-8 1744 1314 -24.66% benchmark old allocs new allocs delta BenchmarkIssue10335-8 4 3 -25.00% BenchmarkUnmapped-8 18 4 -77.78% benchmark old bytes new bytes delta BenchmarkIssue10335-8 320 312 -2.50% BenchmarkUnmapped-8 568 344 -39.44% Fixes #17914, improves #10335 Change-Id: I7d4258a94eb287c0fe49e7334795209b90434cd0 Reviewed-on: https://go-review.googlesource.com/33276 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-03-01all: make copyright headers consistent with one space after periodBrad Fitzpatrick
This is a subset of https://golang.org/cl/20022 with only the copyright header lines, so the next CL will be smaller and more reviewable. Go policy has been single space after periods in comments for some time. The copyright header template at: https://golang.org/doc/contribute.html#copyright also uses a single space. Make them all consistent. Change-Id: Icc26c6b8495c3820da6b171ca96a74701b4a01b0 Reviewed-on: https://go-review.googlesource.com/20111 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-02-24all: fix typos and spellingMartin Möhrmann
Change-Id: Icd06d99c42b8299fd931c7da821e1f418684d913 Reviewed-on: https://go-review.googlesource.com/19829 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
2015-07-27encoding/json: add JSON streaming parse APIPeter Waldschmidt
This change adds new methods to Decoder. * Decoder.Token steps through a JSON document, returning a value for each token. * Decoder.Decode unmarshals the entire value at the token stream's current position (in addition to its existing function in a stream of JSON values) Fixes #6050. Fixes #6499. Change-Id: Iff283e0e7b537221ae256392aca6529f06ebe211 Reviewed-on: https://go-review.googlesource.com/9073 Reviewed-by: Russ Cox <rsc@golang.org>
2015-06-18encoding/json: Remove extra allocation in scanner.Peter Waldschmidt
When the scanner receives a non-whitespace character in stateEndTop, it creates an error message and caches it to return on the next transition. nextValue() uses the scanner to sub-scan for a value inside a larger JSON structure. Since stateEndTop is triggered *after* the ending byte, whatever character immediately follows the sub-value gets pulled into the scanner's state machine as well. Even though it is not used and doesn't cause an error, it does cause the state machine to allocate an error that will never be used. The fix is to probe the state machine with whitespace after scanEndObject or scanEndArray to see if the next character would result in a scanEnd state transition. If so, we can return right away without processing the next character and avoid triggering an allocation. benchmark old ns/op new ns/op delta BenchmarkCodeEncoder 17022194 16611336 -2.41% BenchmarkCodeMarshal 18443250 18090144 -1.91% BenchmarkCodeDecoder 61502053 61010936 -0.80% BenchmarkCodeUnmarshal 61410829 60363605 -1.71% BenchmarkCodeUnmarshalReuse 59124836 58361772 -1.29% BenchmarkUnmarshalString 602 603 +0.17% BenchmarkUnmarshalFloat64 535 537 +0.37% BenchmarkUnmarshalInt64 482 482 +0.00% BenchmarkIssue10335 1206 799 -33.75% BenchmarkSkipValue 17605751 18355391 +4.26% BenchmarkEncoderEncode 612 604 -1.31% benchmark old MB/s new MB/s speedup BenchmarkCodeEncoder 114.00 116.82 1.02x BenchmarkCodeMarshal 105.21 107.27 1.02x BenchmarkCodeDecoder 31.55 31.81 1.01x BenchmarkCodeUnmarshal 31.60 32.15 1.02x BenchmarkSkipValue 111.63 107.07 0.96x benchmark old allocs new allocs delta BenchmarkIssue10335 11 4 -63.64% BenchmarkEncoderEncode 2 2 +0.00% benchmark old bytes new bytes delta BenchmarkIssue10335 376 272 -27.66% BenchmarkEncoderEncode 40 40 +0.00% Fixes #10335 Change-Id: I3d4f2b67f7a038adfb33ba48bb6b680f528baf18 Reviewed-on: https://go-review.googlesource.com/9074 Reviewed-by: Russ Cox <rsc@golang.org>
2014-09-08build: move package sources from src/pkg to srcRuss Cox
Preparation was in CL 134570043. This CL contains only the effect of 'hg mv src/pkg/* src'. For more about the move, see golang.org/s/go14nopkg.