Avoid parsing numbers when using RPCv2 protocol
Motivation and Context
The current unmarshalling process is split into two phases. During the first phase the input is parsed into a JsonNode instance that represents the whole JSON input. The second phase uses this JsonNode to unmarshall the nodes into SDK pojos.
For a regular JSON input the input, numeric values are represented as strings (e.g., 3.14, "17"), therefore we need to parse the strings to convert them into a numeric type. For Smithy RPCv2 we don't need this, the values in the CBOR payload are already encoded in a way that's a lot cheaper to convert than parsing the string.
This change makes it possible to read from the CBOR input the encoded values without having to convert them into strings and back into numbers. For that it changes the two phases of the unmarshalling process:
- During parsing, instead of creating a regular
JsonNode, we create aEmbeddedObjectJsonNodewhich can carry anyObjectwith the numeric value. For that, we introduce a new abstractionJsonValueNodeFactorywhich is used to create nodes for simple types which creates plainJsonNodeby default but a different implementation createsEmbeddedObjectJsonNodefor CBOR payloads. - During unmarshalling we detect those values and use them directly instead of parsing their string values.
Benchmarks
The benchmarks results show below are from unmarshalling a single value of a shape similar to GetMetricData (see here), similar to getting a set of datapoints from a time series (each datapoint is a pair of the time and a floating point value). For the test we labeled 3 samples with "small", "medium", and, "big", and those vary by the amount of datapoints. The labeled "small" has 17, the one labeled "medium" has 37, and, finally the one labeled "big" has 157 datapoints.
The full benchmark results are shown below (showing only for unmarshall, no changes in the marshall results). The summary of how Smithy RPCv2 implementation compares with AWS-JSON is:
After
- small 2.5x faster than json
- medium 2.8x faster than json
- big 3.7x faster than json
Before
- small 1.23x slower than json
- medium 1.05x slower than json
- big 1.22x slower than json
After this change
Benchmark (protocol) (size) Mode Cnt Score Error Units
JsonMarshallerBenchmark.unmarshall smithy-rpc-v2 small avgt 5 8,021.875 ± 199.474 ns/op
JsonMarshallerBenchmark.unmarshall aws-json small avgt 5 15,630.801 ± 113.576 ns/op
JsonMarshallerBenchmark.unmarshall smithy-rpc-v2 medium avgt 5 12,655.069 ± 122.454 ns/op
JsonMarshallerBenchmark.unmarshall aws-json medium avgt 5 29,624.410 ± 913.256 ns/op
JsonMarshallerBenchmark.unmarshall smithy-rpc-v2 big avgt 5 37,135.590 ± 531.297 ns/op
JsonMarshallerBenchmark.unmarshall aws-json big avgt 5 110,714.788 ± 389.752 ns/op
Before this change
Benchmark (protocol) (size) Mode Cnt Score Error Units
JsonMarshallerBenchmark.unmarshall smithy-rpc-v2 small avgt 5 20,204.149 ± 152.628 ns/op
JsonMarshallerBenchmark.unmarshall aws-json small avgt 5 16,424.807 ± 378.576 ns/op
JsonMarshallerBenchmark.unmarshall smithy-rpc-v2 medium avgt 5 35,466.582 ± 172.311 ns/op
JsonMarshallerBenchmark.unmarshall aws-json medium avgt 5 33,548.364 ± 799.947 ns/op
JsonMarshallerBenchmark.unmarshall smithy-rpc-v2 big avgt 5 137,709.264 ± 1920.922 ns/op
JsonMarshallerBenchmark.unmarshall aws-json big avgt 5 112,142.916 ± 306.063 ns/op
Modifications
Testing
Screenshots (if appropriate)
Types of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
Checklist
- [ ] I have read the CONTRIBUTING document
- [ ] Local run of
mvn installsucceeds - [ ] My code follows the code style of this project
- [ ] My change requires a change to the Javadoc documentation
- [ ] I have updated the Javadoc documentation accordingly
- [ ] I have added tests to cover my changes
- [ ] All new and existing tests passed
- [ ] I have added a changelog entry. Adding a new entry must be accomplished by running the
scripts/new-changescript and following the instructions. Commit the new file created by the script in.changes/next-releasewith your changes. - [ ] My change is to implement 1.11 parity feature and I have updated LaunchChangelog
License
- [ ] I confirm that this pull request can be released under the Apache 2 license
Quality Gate failed
Failed conditions
41.6% Coverage on New Code (required ≥ 80%)
C Reliability Rating on New Code (required ≥ A)
See analysis details on SonarCloud
Catch issues before they fail your Quality Gate with our IDE extension
SonarLint