-
Notifications
You must be signed in to change notification settings - Fork 61
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
[api] Add support for "pre-encoded keys" ala Jacksons SerializedString #340
Comments
The following is a JMH benchmark writing to json comparing:
I believe this benchmark is showing me that there are 2 performance techniques that jackson core makes available that are not available via json-p api. These techniques are used by ObjectMapper and also by avaje-jsonb (my library) when it uses jackson core. The first technique is this issue, that the binding library (jackson objectmapper and avaje-jsonb) can provide a Jackson SerialisedString as the key instead of a plain String. Adding this could help move the through put of The results with gc profiling:
|
Wider keys -> more benefitGiven the 2 models: package org.example.jmh.model;
import io.avaje.jsonb.Json;
@Json
public record NarrowNamesRecord(
String a,
String b,
String c,
String d,
String e
) {
} package org.example.jmh.model;
import io.avaje.jsonb.Json;
@Json
public record WideNamesRecord(
String firstNameProperty1,
String lastNameProperty2,
String anotherSimilarProperty3,
String moreOrLessProperty4,
String lastButNotLeastProperty5
) {
} The following benchmark compares the relative throughput when comparing models with relatively narrow keys vs wider keys. We expect the benefit from the use of SerializedString to be more pronounced when the keys are relatively wider as the generator is able to skip more encoding of keys.
Note the test data for this is:
|
With a local prototype I can see a 17% through put improvement with the "prepared keys" in the wide key case. We see that in the 1800 to 2112 values below.
With the narrow key case we expect very little difference, we want to make sure we don't get degraded performance and we see that:
This is still short of what avaje-jsonb is getting via using jackson-core, and short of jackson objectmapper. |
With a local prototype, getting closer to the performance of jackson core. Note this has some additional performance adjustments to parsson internals as well (like removing Scope.IN_FIELD to reduce GC pressure).
|
hm, I'm a bit confused as where does this belong to. Based on the prefix [api] I would think this belongs here but as you are referring to parsson, that would belong to the implementation. Does this need some change in jsonp-api? If not, I would move this back to parsson project... |
Yes it does and yes I think it is fine that the issue is here. Ultimately as I see it we will need to change parsson / the reference implementation as well but it's all good having this here. I have made this a bit confusing. This is pretty much a performance orientated feature. As such I am looking to prove the concept somewhat before I push a PR for the api change (hence the bench marking etc). So yes, I'm making implementation changes at the moment to parsson so that I can:
What we probably could do at some point is create a related issue in parsson but I am happy to progress my work a little more first. |
Ok, I think I've done enough initial bench marking to push for this API change. With respect to this API change we are looking at comparing the jakarta_normalKey and jakarta_preparedKey throughput. We see better throughput can be achieved by using keys that are "prepared" (already escaped and encoded). These benchmarks include a baseline "jsonb_jackson" which is avaje-jsonb using Jackson core 12.13.0, and a baseline "objectMapper" which is Jackson ObjectMapper. Note: Using a modified version of parsson for the jakarta implementation. Changes include using ThreadLocal based buffer recycling
|
Related PR: #344
Related PR in Parsson - eclipse-ee4j/parsson#47
Summary
Create a JsonGenerator.Key
Use a JsonGenerator.Key
I'd like to discuss adding the ability for JsonGenerator to support "pre-encoded" keys as a performance optimisation along the lines of Jacksons SerializedString .
That is, Jackson JsonGenerator has writeFieldName(SerializableString key) ... and I'd love to see that added to the jakarta json api.
SerializedString is the implementation of SerializableString which has pre-encoded the String value into bytes.
This allows the underlying generators to effectively do array copy of the already encoded bytes.
https://github.com/FasterXML/jackson-core/blob/2.14/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java#L282
Background:
I have been doing JMH performance benchmarks around this area and with jackson core, the use of SerializableString for the "field names" aka "keys" is significant - how significant depends on the relative width of the keys vs values. For relatively wide keys and narrow values it is really significant.
More background, I'm working on avaje-jsonb which uses APT source code generation to do json binding. avaje-jsonb currently abstracts over jackson code and now jakarta json (so I'm doing direct comparison between parsson and jackson-core in this manor). Currently this is an important performance feature that I see with the jackson core adapter.
The text was updated successfully, but these errors were encountered: