ObjectReader prefetch performance

1,039 views
Skip to first unread message

tomsmit...@gmail.com

unread,
Sep 21, 2015, 1:24:46 AM9/21/15
to jackson-user
Hi:

To deserialize a Json string of class T, I could do
ObjectReader objectReader = OBJECT_MAPPER.reader(T.class);

objectReader.readValue(jsonString)

but this would rrquire creating one reader per class/type
How about using one reader object

ObjectReader objectReader = OBJECT_MAPPER.reader();

objectReader.readValue(jsonString,T.class)

so a single reader can be used for all classes.
Does it have significant performance difference with the two approaches?

Thanks

Tatu Saloranta

unread,
Sep 21, 2015, 2:24:22 PM9/21/15
to jackso...@googlegroups.com
The whole idea is that readers are fully immutable, including definition of target type. Further, adding an overloaded readValue() method would cause explosion of methods for all different input types, and 3 ways to define target type (Class, TypeReference, JavaType).
So I do not think we will ever add such variant; omission is purposeful, not accident.

Cost of constructing ObjectReader should be trivial, so I wouldn't worry about that too much.
You can construct alternative instances using "reader.forType(...)", so you could still have a base ObjectReader to use, and just create a variant as needed.

-+ Tatu +-


--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

tomsmit...@gmail.com

unread,
Sep 21, 2015, 3:12:30 PM9/21/15
to jackson-user
Sorry  my question.was not clear.
To deserialize a json string of type  List<UserBean>, with existing API of 2.6
I could do 

ObjectReader objectReader = OBJECT_MAPPER.reader(new TypeReference<List<UserBean>>{}());
or

ObjectReader objectReader = OBJECT_MAPPER.reader(<predefined JavaType>);
and do
objectReader.readValue(jsonString)
which "readValue" method call is faster (or the same): javatype or typereference?
Separately, I could do this (with existing API of 2.6

ObjectReader objectReader = OBJECT_MAPPER.reader();
objectReader.readValue(
new TypeReference<List<UserBean>>{}())
is "readValue" method call this way significantly slower than the first approach?
(Does Jackson internally cache the type info after first method call so the following calls
will not require reexamination).

The motivation of my question is that if I could define a single reader (instead of many)
and still have same performance after initial call. Also, what is the fastest way to
deserialize
List<UserBean> as I read it could be slow with typereference approach.


Tatu Saloranta

unread,
Sep 21, 2015, 3:22:34 PM9/21/15
to jackson-user
Ah ok. JavaType is the fastest way to indicate type information, so it is preferable to TypeReference or even simple Class.

ObjectReader does (optionally) pre-fetch the underlying JsonDeserializer, so if you construct and retain ObjectReader, it can avoid both type resolution (TypeReference -> JavaType) and JsonDeserializer look up for root value. If so, reusing ObjectReader as-is (without changing type; other re-configuration is fine) will be more efficient than constructing a new instance from ObjectMapper.

As to List<X>, as long as you use JavaType, it should not have significant performance overhead. Type resolution for figuring out type parameters (generic type of element), from TypeReference, does take some time. Whether it matters a lot depends on use case: in grand scheme of things it may not really matter.

It may make sense to write a very simple jmh-based test for your use case, if you really want to see difference between approaches for your specific case. I think this is actually useful thing to try, and once you have done it once it takes very little time.
As a baseline you could check out:

https://github.com/FasterXML/jackson-benchmarks

which I use for comparing performance of various dataformats via Jackson.
which compares various Java JSON libraries, including jackson and jackson-jr.
There is nothing particularly interesting per se, but shows one way to use jmh for (micro-)benchmarks.

-+ Tatu +-

tomsmit...@gmail.com

unread,
Sep 21, 2015, 4:02:24 PM9/21/15
to jackson-user
Got it.  I think the simplest yet high performance approach would be

ObjectReader objectReader = OBJECT_MAPPER.reader();
objectReader.readValue(
jsonString, JavaType)

this would avoid creating many readers. Only need to define different types.
Since the javatype is provided, prefetch would not matter anymore.

Thanks very much.

tomsmit...@gmail.com

unread,
Sep 23, 2015, 5:10:29 PM9/23/15
to jackson-user
Hi,
I think I might be too quick to draw conclusion on this.
so now my question is, what is the performance difference between the two approach below
1)
ObjectReader objectReader = OBJECT_MAPPER.reader();
objectReader.readValue(
jsonString, JavaType)

2)
ObjectReader objectReader = OBJECT_MAPPER.reader(JavaType);
objectReader.readValue(
jsonString)
...

Tatu Saloranta

unread,
Sep 23, 2015, 7:32:20 PM9/23/15
to jackso...@googlegroups.com
Only one of those methods, (2), exists... :)

So use method (2). It'll work fine.

-+ Tatu +-

--

tomsmit...@gmail.com

unread,
Sep 23, 2015, 10:18:55 PM9/23/15
to jackson-user
Sorry my bad. somehow I mixed up.
while on this, below two methods do exist


reader = OBJECT_MAPPER.reader(JavaType);
and
reader = OBJECT_MAPPER.reader(TypeReference);

Are they the same for performance when using reader later?
Is TypeReference intervally converted to JavaType?
...

Tatu Saloranta

unread,
Sep 23, 2015, 10:47:23 PM9/23/15
to jackson-user
Yes, TypeReference is internally converted to JavaType, adding some overhead.

-+ Tatu +-


--

tomsmit...@gmail.com

unread,
Sep 23, 2015, 10:50:59 PM9/23/15
to jackson-user
But the overhead is only during the reader creation, correct,
once reader is created, it should not have any performance difference
for future readValue()  call, correct?
...

Tatu Saloranta

unread,
Sep 24, 2015, 12:22:46 AM9/24/15
to jackson-user
Correct.

-+ Tatu +-

--

tomsmit...@gmail.com

unread,
Sep 24, 2015, 8:14:46 AM9/24/15
to jackson-user
Thanks very very much for your great help.
Message has been deleted

Tatu Saloranta

unread,
Oct 4, 2015, 1:28:16 PM10/4/15
to jackson-user
ObjectMapper will indeed cache root-level serializers/deserializers.
Construction of JavaType is not cached as part of this set up, as ObjectMapper calls TypeFactory to construct JavaType before checking cache.
ObjectReader will further simplify this by pre-fetching JsonDeserializer (via cache) once, so even that lookup is eliminated.

But at this point if you are really worried about performance, you should actually measure it by benchmarking using same usage patterns you would be using.
You can not know exact performance from static knowledge of kinds of things done.

At the same time, performance difference I would expect from JavaType construction and pre-fetching would not be huge; certainly no more than 5-10% even for simplest cases. And time spent by Jackson is typically not majority either; perhaps 10-30% of total processing (depending on what is being done). So another question to ask is whether you have a problem to solve, or potential future optimization you are doing now.

Good luck with performance testing!

-+ Tatu +-




On Sun, Oct 4, 2015 at 9:54 AM, <tomsmit...@gmail.com> wrote:
Hi, Tatu:

Sorry for my stubbornness this topic. But I am seeing from url

http://wiki.fasterxml.com/JacksonBestPracticesPerformance

ObjectMapper: object mappers cache serializers and deserializers that are created first time handler is needed for given type

Does it mean ObjectMapper will cache many serializers/deserialzers (and all the JavaTypes) of many Object types  so after first uses of all those object types),
 it will have no overhead and would have similar
performance to using specific type of ObjectReader/ObjectWriter?

In other words, i could use a single ObjectMapper instance for all the work in performance
perspective since internall it will generate needed JavaTypes after first uses and cache it
for later use.

...
Reply all
Reply to author
Forward
0 new messages