Skip to content

Reduce allocations in sortKeysMapEncoder #424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 21, 2019

Conversation

aaronbee
Copy link
Contributor

@aaronbee aaronbee commented Dec 3, 2019

Use one buffer for all encoded keys and values.

This significantly reduces allocations in my test of an array of 18 objects and each object has six fields.

benchmark                                old ns/op     new ns/op     delta
BenchmarkArrayJSONMarshal/jsoniter-8     67619         62885         -7.00%

benchmark                                old allocs     new allocs     delta
BenchmarkArrayJSONMarshal/jsoniter-8     500            393            -21.40%

benchmark                                old bytes     new bytes     delta
BenchmarkArrayJSONMarshal/jsoniter-8     30917         20421         -33.95%

It also brought allocations below the stdlib implementation for this test:

BenchmarkArrayJSONMarshal/stdlib-8         	   13418	     89073 ns/op	   26984 B/op	     466 allocs/op

Use one buffer for all values.
@@ -310,7 +310,7 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
encoder.elemEncoder.Encode(elem, subStream)
keyValues = append(keyValues, encodedKV{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is the other large source of allocations for this code. Inside this function do we have access to the length of mapIter? If so, this slice could be correctly sized when it is instantiated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initializing the keyValues slice to be size 8 saved another 25% in bytes allocated in my test. 8 will not always be the best value, but I think it's better than an initial size of 0 in most cases.

To get the actual length of the map, looks like reflect2 would need to expose maplen.

@codecov
Copy link

codecov bot commented Dec 3, 2019

Codecov Report

Merging #424 into master will increase coverage by 0.07%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #424      +/-   ##
==========================================
+ Coverage   86.46%   86.54%   +0.07%     
==========================================
  Files          41       41              
  Lines        5105     5105              
==========================================
+ Hits         4414     4418       +4     
+ Misses        555      551       -4     
  Partials      136      136
Impacted Files Coverage Δ
reflect_map.go 87.68% <100%> (ø) ⬆️
reflect_struct_decoder.go 81.89% <0%> (+0.53%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 44a7e73...f814d6c. Read the comment docs.

@taowen taowen merged commit b681149 into json-iterator:master Dec 21, 2019
zhenzou pushed a commit to zhenzou/jsoniter that referenced this pull request Feb 2, 2022
…ions

Reduce allocations in sortKeysMapEncoder
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants