Optimizing Gson deserialization

17,953

Solution 1

If you want to use Gson, and not switch to another Java-to/from-JSON API, and if the performance of Gson's automagic databinding isn't good enough, then it is possible to stay with the Gson API, and squeeze out some moderately better performance.

In the latest rounds of performance tests posted at https://github.com/eishay/jvm-serializers/wiki, the results suggest that the combined performance of Gson serialization and deserialization could possibly be improved by about 25%, by using the streaming API of Gson instead of databinding.

Note that this generally significantly complicates the implementation of the user code, where solutions comparable to one-liners using the databinding API, e.g., new Gson().toJson(something), are replaced with (easily) dozens of lines, including loops and conditionals. So, the cost of the improved performance is more complicated code.

For examples of using the streaming API versus the databinding API, take a look at the JsonGsonManual and JsonGsonDatabind implementations, in the jvm-serializers project.

(Note: One could also use the tree-model in the Gson API, instead of the streaming or databinding APIs, but it doesn't appear to offer any performance improvements over databinding. For an example, see JsonGsonTree.)

Solution 2

There is no way to improve the Gson library serialization and deserialization time.

As Programmer Bruce said, if the execution time really matters to you, take a look at the Jackson library. It is, in my opinion, a little bit more "complicated" to use but it has been proven much faster than any other json libraries in benchmarks.

Here are some best practices to improve performances with Jackson.

Solution 3

Gson is known and use for it's ease of use. If you want speed you will have to look at the super popular Jackson Json.

I have tested and benchmarked both Gson and Jackson and I can tell you that in some use cases Jackson is 15 times faster on both serialization and deserialization, even on very big objects.

To get similar behavior as Json I use the following settings

public enum JsonMapper {
    INSTANCE;

    private final ObjectMapper mapper;

    private JsonMapper() {
        mapper = new ObjectMapper();
        VisibilityChecker<?> visibilityChecker = mapper.getSerializationConfig().getDefaultVisibilityChecker();
        mapper.setVisibilityChecker(visibilityChecker
                .withFieldVisibility(Visibility.ANY)
                .withCreatorVisibility(Visibility.NONE)
                .withGetterVisibility(Visibility.NONE)
                .withSetterVisibility(Visibility.NONE)
                .withIsGetterVisibility(Visibility.NONE));
    }

    public ObjectMapper mapper() {
        return mapper;
    }
}

This will turn out to give the exact same json strings as Gson for the same objects. You can set it to use only getters and setters if you want to. I'd advise you to read about all the jackson json annotations for handling subtypes (useful for RPC-style systems).

My use cases : I use jackson as serialization when I need to save blobs to storage systems (Redis, Cassandra, Mongo, ... sometime mysql too). I also use it as the serialization for my RPC-style APIs for fairly high traffic systems, although I prefer using Protobuf for those when possible. In this last case I use Jackson to directly serialize to byte[] or stream for better performance.

One last note : The object mapper is thread safe and having one static instance like in the example I just submitted will prevent you from having the slight instantiation overhead.

EDIT : I am aware that my example doesn't follow a lot of the best practices pointed out in the jackson page but it allows me to have simple to understand code that looks like the Gson.toJson and Gson.fromJson (which I started with too and switched on later to Jackson)

Gson.toJson(object) => JsonMapper.INSTANCE.mapper().writeValueAsString(object) Gson.fromJson(object, clazz) => JsonMapper.INSTANCE.mapper().readValue(jsonString, clazz);

Solution 4

I'd switch to Jackson, and consider other solutions much faster than Gson in benchmarks.

Share:
17,953

Related videos on Youtube

HandlerExploit
Author by

HandlerExploit

Updated on July 18, 2022

Comments

  • HandlerExploit
    HandlerExploit almost 2 years

    What is the best way to optimize deserialization?

    I am currently using the standard Gson.toJson and Gson.fromJson methods for serialization and deserialization of some complex objects and I am looking to reduce deserialization time if its possible.

    The most complex of my object contains 43 variables if that matters.

  • Programmer Bruce
    Programmer Bruce about 11 years
    Agreed (obviously). I'd add that while the configuration options with Jackson are vast and much more significant than those available with the Gson API, for the simple use case of mapping between data structures requiring minimal custom processing, Jackson, like Gson, provides for a simple one line solution.
  • xarlymg89
    xarlymg89 over 5 years
    Jackson is definitely slower for manual parsing (using streaming API). In my use case at least, with a 20MB uncompressed JSON file, the difference in parsing time was that Gson was almost 5 times faster than Jackson.