I recently upgrade my app from a very old version of spring-boot (and hateoas) to the latest boot and hateoas v1.1.2.RELEASE. After this I am seeing a spike in memory usage. Heap dump points to WebHandler.AFFORDANCES_CACHE consuming most of memory. Looking at WebHandler it seems that the cache is never cleared and is unbounded... has anyone faced this issue ?
Here is the link to a simple project which exposes a /users/{id}. If we call this api with enough distinct id values, it causes AFFORDANCES_CACHE to fill up. https://github.com/ravishrathod/spring-hateoas-memory
While technically we're using a ConcurrentReferenceHashMap, which means that it will eventually wipe entries on GC, I'll change the cache to rather be a ConcurrentLruCache limited to 256 entries.
Hi! It looks like this PR makes big performance regression for my project. As there is a contention on LRU cache locks. We're creating thousands of links concurrently and threads have to wait for each other. @odrotbohm could you revert that PR?
Here you can see part of profiling my app:

Before that change there is no wall-clock time on that locks.
The reason of that is the ConcurrentReferenceHashMap. It doesn't lock on get() method while ConcurrentLruCache$get uses ReentrantReadWriteLock.
@odrotbohm just to show you the scale of the problem that @wyhasany described - we had to downgrade Spring Boot from 2.4.3 to 2.4.1 because average response time in our project increased 10 times, from 7ms to 70ms

Would you mind opening a new ticket to properly keep track of the problem?
@odrotbohm ofc, I'm just doing it
Most helpful comment
Hi! It looks like this PR makes big performance regression for my project. As there is a contention on LRU cache locks. We're creating thousands of links concurrently and threads have to wait for each other. @odrotbohm could you revert that PR?
Here you can see part of profiling my app:

Before that change there is no wall-clock time on that locks.
The reason of that is the
ConcurrentReferenceHashMap. It doesn't lock onget()method whileConcurrentLruCache$getusesReentrantReadWriteLock.