这是indexloc提供的服务,不要输入任何密码
Skip to content

Performance improvement of strictNullCheck #719

@k163377

Description

@k163377

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions