SlidingExpiration and MemoryCache

前端 未结 1 1010
说谎
说谎 2021-02-18 15:16

Looking at the documentation for MemoryCache I expected that if an object was accessed within the Expiration period the period would be refreshed. To be honest I think I inferre

1条回答
  •  感动是毒
    2021-02-18 15:26

     ... new CacheItemPolicy {SlidingExpiration = TimeSpan.FromSeconds(1) }
    

    This is not adequately documented in MSDN. You were a bit unlucky, 1 second is not enough. By a hair, use 2 seconds and you'll see it works just like you hoped it would. Tinker some more with FromMilliseconds() and you'll see that ~1.2 seconds is the happy minimum in this program.

    Explaining this is rather convoluted, I have to talk about how MemoryCache avoids having to update the sliding timer every single time you access the cache. Which is relatively expensive, as you might imagine. Let's take a shortcut and take you to the relevant Reference Source code. Small enough to paste here:

        internal void UpdateSlidingExp(DateTime utcNow, CacheExpires expires) {
            if (_slidingExp > TimeSpan.Zero) {
                DateTime utcNewExpires = utcNow + _slidingExp;
                if (utcNewExpires - _utcAbsExp >= CacheExpires.MIN_UPDATE_DELTA || utcNewExpires < _utcAbsExp) {
                    expires.UtcUpdate(this, utcNewExpires);
                }
            }
        }
    

    CacheExpires.MIN_UPDATE_DELTA is the crux, it prevents UtcUpdate() from being called. Or to put it another way, at least MIN_UPDATE_DELTA worth of time has to pass before it will update the sliding timer. The CacheExpired class is not indexed by the Reference Source, a hint that they are not entirely happy about the way it works :) But a decent decompiler can show you:

    static CacheExpires()
    {
        MIN_UPDATE_DELTA = new TimeSpan(0, 0, 1);
        MIN_FLUSH_INTERVAL = new TimeSpan(0, 0, 1);
        // etc...
    }
    

    In other words, hard-coded to 1 second. With no way to change it right now, that's pretty ugly. It takes ~1.2 seconds for the SlidingExpiration value in this test program because Thread.Sleep(100) does not actually sleep for 100 milliseconds, it takes a bit more. Or to put it another way, it will be the 11th Get() call that gets the sliding timer to slide in this test program. You didn't get that far.

    Well, this ought to be documented but I'd guess this is subject to change. For now, you'll need to assume that a practical sliding expiration time should be at least 2 seconds.

    0 讨论(0)
提交回复
热议问题