Despite it works great to avoid buffer leaks in dev mode or for the Quarkus blocking thread pool ThreadLocal(s), soft reference management can be very dangerous and unstable in the container world, where the (scarse) available MBs of heap can cause unexpected soft reference collections, causing new (big) jackson recyclers allocations, harming runtime performance and, again, the available memory bandwidth to the rest of application (instead of saving it).
An example of this is the json benchmark at Techempower, which, for some weird reason (test duration vs available MB in the heap), was triggering re-allocation of soft references and recycler, as by this flamegraph
In order to reproduce it, just setup a small enough max heap capacity eg 20 MB, occupy 19 MB of it (in JMH just retaining byte[]s for that), and leaving 1 MB available: the default value of SoftRefLRUPolicyMSPerMB will keep the soft reference of the recycler alive for 1 second per MB of available heap (which is 1, here), then it will free it up.
Description
The default Jackson thread local pool is using https://github.com/FasterXML/jackson-core/blob/2.17/src/main/java/com/fasterxml/jackson/core/util/JsonRecyclerPools.java#L125 which, under the hood, uses https://github.com/FasterXML/jackson-core/blob/2.17/src/main/java/com/fasterxml/jackson/core/util/JsonRecyclerPools.java#L132 to reuse a
BufferRecycler
stored in a soft reference'sThreadLocal
at https://github.com/FasterXML/jackson-core/blob/28fce9b4b7c48d2f70f244536ad284f1f52345ab/src/main/java/com/fasterxml/jackson/core/util/BufferRecyclers.java#L60Despite it works great to avoid buffer leaks in dev mode or for the Quarkus blocking thread pool ThreadLocal(s), soft reference management can be very dangerous and unstable in the container world, where the (scarse) available MBs of heap can cause unexpected soft reference collections, causing new (big) jackson recyclers allocations, harming runtime performance and, again, the available memory bandwidth to the rest of application (instead of saving it).
An example of this is the json benchmark at Techempower, which, for some weird reason (test duration vs available MB in the heap), was triggering re-allocation of soft references and recycler, as by this flamegraph
FYI the soft reference collection policy works based on the default
SoftRefLRUPolicyMSPerMB
values as explained very well at https://www.michaelpollmeier.com/2019/04/09/understanding-jvm-soft-references-for-great-good-and-building-a-cache: have fun and be horrified by this diabolic behaviour.In order to reproduce it, just setup a small enough max heap capacity eg 20 MB, occupy 19 MB of it (in JMH just retaining byte[]s for that), and leaving 1 MB available: the default value of
SoftRefLRUPolicyMSPerMB
will keep the soft reference of the recycler alive for 1 second per MB of available heap (which is 1, here), then it will free it up.Implementation ideas
No response