Jackson Best Practices: Performance

Jackson is designed to add minimum amount of overhead for your JSON processing. But just like other high-performance engines, actual real-life performance is dependant on usage patterns. Here are some things you can do to ensure efficient operation.

1. Reuse when appropriate

Some objects that Jackson package use are either expensive to create, or can reuse other things that are expensive to create. This is specifically true for following objects:

Fortunately reuse of these objects is very easy: they are thread-safe provided that configuration is done before any use (and from a single thread). After initial configuration use is fully thread-safe and does not need to be explicitly synchronized.

Some other commonly used objects may be reused, but where benefits are much fewer:

2. Clean up after use

As a general rule, you should close all objects that are closeable, after you are done with them. This means closing:

instances once you are done with them.

Why does this matter? Some resources (internal buffers) can be released when instances are closed, and will be reusable later on for other instances (handled by JsonFactory that creates instances). This matters most when handling small JSON documents, but is a good practice to follow in general.

3. Use the "least processed" forms of input source

(and output targets)

In general, Jackson is optimized for use cases where input is given in its raw form, and can do all necessary transformations and buffering very efficiently. Consider following:

Another way to put these is that it is unlikely that you can help a lot by pre-processing things. Sort of like you should not try to "help" plumber when he comes to unclog your toilet -- let expert do his/her job.

4. Change defaults only when you need to

As a general rule, default settings are chosen for optimal (or at least good enough!) performance: and all "slow features" need to be specifically enabled. Although most configurable features do not have significant performance impacts, some do: and usually mostly because they implement less often needed functionality and thus have not been extensively optimized. Because of this, it makes sense to use default settings unless you specifically need non-default settings.

Examples of settings that can reduce performance.

As with other minor performance concerns, it makes sense to measure effects if you really want to optimize performance -- it may be that you can not see enough difference for settings to really matter.

5. If you need to re-process, replay, don't re-parse

In cases where you can not process JSON content in one fell swoop, you do not have to (and should not!) serialize intermediate results back into textual JSON: this because reading and writing of textual JSON is still somewhat costly, even with fast processor like Jackson. Instead, you can use more efficient intermediate forms, such as:

Use of either JsonNode or TokenBuffer can boost performance nicely in cases where incremental processing is necessary. Further, due to wide range of available conversions, resulting code can be simple and easy to follow as well.

6. Static typing

Static types are slightly more efficient for serialization: for example, if a class is known to be final, serializer functionality may be able to avoid some of type checking. So although it probably does not make sense to add 'final' modifiers just for this purpose (speed difference is unlikely to be huge; typically in range of 10 - 20% for raw serialization), it is nice to know that this can have some positive performance benefit.

7. Prefer ObjectReader/ObjectWriter over ObjectMapper

Although the main reason to prefer these objects is thread-safety (and thus correctness), there may be performance benefits as well. Latest Jackson versions (2.1 and above) will be able to reuse root-level (de)serializers, making reuse of ObjectReaders and ObjectWriters bit more efficient than using ObjectMapper.

8. Use ObjectReader.readValues for sequences

When reading a root-level sequence of POJOs, readValues() method of ObjectReader can be much more efficient than doing explicit iteration using ObjectMapper.readValue() method.


CategoryJackson

JacksonBestPracticesPerformance (last edited 2012-07-19 18:51:13 by TatuSaloranta)

Copyright ©2009 FasterXML, LLC