-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[FeatureRequest] support set a different exprie time when add a cache entry #114
Comments
Hi Jiming, You can modify the expiration times at runtime using The reason why per-entry expiration times isn't provided is that it is difficult to implement efficiently. The fixed expiration times is performed as O(1) operations by moving nodes in a linked list to maintain order. This works because we know the accessed entry is the least likely to expire, so its pushed to the end of the list. We can then peek at the front knowing that if it hasn't expired, no entries behind it have too. We can't use that trick if an entry's expiration time varies. This leads to a few common approaches which are each problematic.
Of the choices, I'm prone to using a timer wheel. But that requires experimentation and understanding how implementors have resolved performance issues. I've never seen it used for caches and its not a widely known technique, so contributions exploring this would be helpful. For the time being, I'd recommend using your own timestamp and relying on size eviction. That should be simple to code. |
Hi Ben, Got it, thanks a lot for the detailed answer! Best regards! |
@ben-manes, when you're saying |
That idea is called negative caching, where you use a placeholder to indicate its absence to avoid query storms. If you use your own timestamp, then you can check if the entry is expired and, if so, use I started working on variable expiration over the weekend. That would support your use-case naturally and operates in amortized O(1) time. The timer wheel needs more tests and bug fixes, and it needs to be integrated into the cache. Please take a look at the interface and let me know your thoughts. |
Caffeine.newBuilder()
.expireAfter(new Expiry<Key, Graph>() {
public long expireAfterCreate(Key key, Graph graph, long currentTime) {
return (graph instanceof NullGraph)
? TimeUnit.MINUTES.toNanos(1)
: TimeUnit.MINUTES.toNanos(10);
}
public long expireAfterUpdate(Key key, Graph graph,
long currentTime, long currentDuration) {
return currentDuration;
}
public long expireAfterRead(Key key, Graph graph,
long currentTime, long currentDuration) {
return currentDuration;
}
})
.build(key -> createExpensiveGraph(key)); Note that the other methods return |
Thanks @ben-manes, you're the man! |
There shouldn't be. It is amortized O(1), currently optimized for durations up to 6.5 days (not restricted by that, just not as optimal). If feedback that durations longer than a week is common then we can tune that, but it seemed like a safe bet for what I've seen. The amortized penalty (cascading in a hierarchical timer wheel) is deferred to the executor, which by default is JMH benchmarks showed that the operations were very fast, e.g. at about a dozen nanoseconds to reschedule. Of course the That said, please do let me know if you observe any negative behaviors. |
Hi Ben,
Sometime, we need set the exprie time for certain cache entry, such as to an NullObject entry, I want it's expired time is one tenth of the global cache setting. Could you please consider add a method to support it?
And another feature useful is to change ttl of a cache, which is useful when I wanted to gracefully upgrade or downgrade system setting. I hope the ttl of cache can be longer or shorter
Thanks.
Jiming
The text was updated successfully, but these errors were encountered: