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
Feature request: Add a softEntries() build method that will remove both the cached value and its key when memory is almost full #674
Comments
When references caching is used then the cache will compare using identity ( Since a strong reference to the key is needed for lookup, this causes The cache key is usually very light and inexpensive whereas the value may be heavier. In that case it likely wouldn't make sense to make the key evictable when the value is strongly reachable, as the JVM won't free up much memory. The case of
This appears to be the root issue and is simply a misunderstanding. When the value is garbage collected then the entire entry is eligible for removal. It may reside temporarily in the cache, just like an entry's whose time-to-live has expired, but it will be detected and discarded during a maintenance cycle. The cache operations will treat it externally as if the entry was absent. In practice soft references are more problematic than expected, so we prefer an explicit maximum size/weight instead for memory management. The two main reasons are,
It is easier to defer decisions to the JVM but those will be much poorer than your own. By explicitly setting a maximum and exposing statistics then you'll have more predictable performance and fewer surprises. It is a bit more work but the right choice for production workloads. |
Thank you for your swift reply. You say that Thanks |
A strong or weak reference is collected by the garbage collector when it is no longer strongly reachable. A cache holding a soft/weak entry won't evict until the GC clears the reference, adding it to a A soft reference that is not strongly reachable has its collection delayed so that the application can resurrect it as strongly reachable. This encourages using all of the free memory as available to caches to maximize the hit ratio. That causes the heap to be filled, so that new allocations trigger a garbage collection to shrink the cache only as much as needed. This cached data goes against generational hypothesis, it is quickly promoted out of the young generation. When activity requires freeing up memory then the GC will be forced to perform a major collection, which traditionally was a stop-the-world event (CMS, ParallelGC). That changes behavior from being a sawtooth pattern to mimic a memory leak pattern, as it maximizes the heap utilization by freeing only the minimal amount of memory needed. You can combine soft references with another policy, such as size or expiration. That will typically cause the cache to evict the entry early enough so that the heap isn't filled, while also giving a safety valve to cope with an unexpected spike in memory usage. That might sound attractive but it doesn't typically help, has its own overhead, and production traffic tends to prefer failing fast approach to meet performance goals and minimize the blast radius of one customer affecting another. |
Thanks for the explanation Ben-manes. |
Closing. I hope that made sense for why |
I see that
Caffeine.newBuilder()
has the build methodsweakKeys()
,weakValues()
andsoftValues()
. I'm wondering why it doesn't havesoftKeys()
as a method as well.I want the garbage collector to start removing cached values when RAM memory becomes critically full. Thats why i do call the method
softValues()
when creating a new cache manager. However it would be nice if the associated key could also be garbage collected when the value is. It doesn't make sense to let a key reference a null value in this case.So if possible i would like to have a method that wraps an
Map.Entry
instance in a SoftReference. So that when the gc starts collecting both the key AND its associated cached value are simultaneously removed from the cache.I understand that a
Map.Entry
in aSoftReference
can not be added to a regularMap
instance. So in this case theCacheManager
should not be using theMap
it uses by default. But instead it should be using something like apache'sSoftHashMap
for instance. The description of this class is the following:I've highlighted some parts of the description to indicate how useful this class could be when implemented as a dependency in the
Caffeine
library.Could you please consider adding a build method that allows a cachemanager to make use of the
SoftHashMap
from apache ?Thank you
The text was updated successfully, but these errors were encountered: