-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Contention in TypeNameIdResolver.idFromClass()
#2556
Comments
One solution we are thinking of is to copy() the ObjectMapper instance before obtaining a writer (which we then put in a ThreadLocal) |
Results should quickly get cached, so even with synchronization it would seem odd that it would become bottle-neck, so my first suspicion is usually regarding whether something else is not getting reused. I would not recommend copying However: I can change synchronization itself to reduce scope so that (usually successful) lookup, and other processing (introspection of cached id not found, addition to lookup map) are not within same sync block, and use separate sync for put'ing of new value. My main concern is just that I do not have any way to really test this, so if there was a way to test this somehow (like running under profiler) to verify improvement, that'd be great. But I can make a change to get released in 2.10.2 I think; I have made similar changes to synchronized scope in the past, with good results. |
The ThreadLocal copies gave us 10% throughput improvements. We have plenty of memory, so that was a valuable tradeoff. Not sure if we can make a good benchmark, but now that we know where the Threads block, we should be able to compare versions with our loadtests. |
turning |
Jackson-databind can not use Java 8 methods until 3.0, so unfortunately it is not available. |
TypeNameIdResolver.idFromClass()
With fix, it should be possible to build (or use from Sonatype OSS) 2.10.2-SNAPSHOT build to see if change resolved thread block. I am still somewhat surprised as to how it could have resulted in performance problems: after resolving type ids once, they should stick, unless |
We will check it. But you are right. That’s why I proposed the ConcurrentHashMap. I think in our case the successful reads just block (so the synchronized block that is still in). We have around 50k ObjectMapper.writeValue per second. |
That rate does explain why it could matter (impressive that polymorphic handling can scale as that seems like it could add quite a bit of overhead). Alternatively I could be mistaken and it actually is about contested So I guess results from benchmark would be interesting. :) |
Terve @cowtowncoder, I am currently travelling, so please take my benchmarks with a grain of salt. I will re-run them when I have a stable power connection. Our code uses afterburner, so I included that in my benchmarks. I did exchange the map for a Find my benchmark in this gist: I will make a PR to illustrate my CHM change (although its really straightforward, just wrap it in the constructor) |
For 2.10.1
Full Output:
|
For your 2.10.2-SNAPSHOT change:
Full Output:
|
For your 2.10.2-SNAPSHOT change + my CHM change
|
So even the worst result of the |
PR is here: #2557 Thanks for a) your hard work on this framework b) for being so super reactive and c) for considering each and every of the many issues/prs that is reported. |
Still looking for a better public API to bench this on, as the memory allocation for the result makes it a bit noisy |
Fix merged, made a slight change to avoid copying (and had to dig to remember why deserialization case needed non-null map in one edge case, wrt #1198). |
We are using Jackson 2.9.10 and we have many threads serializing Java objects onto kafka.
Under high load (cough, black friday), we see several threads blocking on the type map that is contained in TypeNameIdResolver
I see that this is a
synchronized
block here:https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java#L99
Could that be changed? Should we somehow use several
TypeNameIdResolver
s (how would one do that?The text was updated successfully, but these errors were encountered: