Skip to content
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

Performance improvement of strictNullCheck #719

Open
k163377 opened this issue Oct 28, 2023 · 0 comments
Open

Performance improvement of strictNullCheck #719

k163377 opened this issue Oct 28, 2023 · 0 comments

Comments

@k163377
Copy link
Contributor

k163377 commented Oct 28, 2023

Use case

Currently, if the strictNullChecks option is enabled, the deserialization performance of collections is significantly degraded.
It also reduces the performance of all deserialization, although very slightly.

The following graphs show actual benchmark results.
image
https://github.com/ProjectMapK/kogera-benchmark#original

In jackson-module-kotlin, we are looking for ways to mitigate this performance degradation.

Describe the solution you'd like

Currently, the following two methods have been found

  • Check with Converter
  • Override SetterInfo.contentNulls

As is common with both methods, exceptions and error messages will change.

Check with Converter

The first is to use the following Converter to perform null checks.
https://github.com/ProjectMapK/jackson-module-kogera/blob/b9aca60a58b8a6b135150e8921229d38699475a9/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/deser/Converters.kt#L13-L69

This method has the problem of limiting the information that can be displayed in error messages, but has almost no other restrictions.
In the Kogera experimental implementation, the following error messages are displayed.
At least the properties in error are readable.

package io.github.projectmapk.jackson.module.kogera._integration.deser

// deser target
class ArrayWrapper(val value: Array<Int>)
com.fasterxml.jackson.databind.exc.MismatchedInputException: A null value was entered for the parameter value. (through reference chain: io.github.projectmapk.jackson.module.kogera._integration.deser.StrictNullChecksTest$ArrayWrapper["value"])

The following graph shows the results of a similar benchmark run on Kogera.
You can see that the performance degradation of the deserialization of the collection is smaller.
image
https://github.com/ProjectMapK/kogera-benchmark#kogera

Override SetterInfo.contentNulls

The second is to override SetterInfo.contentNulls.
This has the same behavior as specifying JsonSetter(contentNulls = Nulls.FAIL).

A possible way to achieve this would be to implement AnnotationIntrospector.findSetterInfo.
At this time I am not aware of any other method.
https://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/latest/com/fasterxml/jackson/databind/AnnotationIntrospector.html#findSetterInfo-com.fasterxml.jackson.databind.introspect.Annotated-

The biggest advantage of this approach is that the performance is theoretically the best (although this has not yet been confirmed by benchmarking).
Another advantage is that the implementation in kotlin-module is minimal.

On the other hand, there are some disadvantages with the current possible implementation.

First, it interacts with other AnnotationIntrospectors.
This can be a problem if the contentNulls are custom, since the AnnotationIntrospector is constrained to apply only one of the results(If JsonSetter is explicitly specified, it will be used).

Second, the kotlin-module will no longer customize error messages.
The error message for the ArrayWrapper just described is as follows

com.fasterxml.jackson.databind.exc.InvalidNullException: Invalid `null` value encountered for property "value"
 at [Source: (String)"{"value":[null]}"; line: 1, column: 11] (through reference chain: io.github.projectmapk.jackson.module.kogera._integration.deser.StrictNullChecksTest$ArrayWrapper["value"]->java.lang.Object[][0])

Describe alternatives you've considered

No response

Additional context

No response

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

No branches or pull requests

1 participant