public void ClearAllCachesTest() { const string prefix = "123123af"; var fk1 = FullKey(prefix, "111"); var fk2 = FullKey(prefix, "222"); var memoryCache = new MemoryCache("sdgkmnsdlkghn"); _objectCacheFactory.Setup(x => x.Create()).Returns(memoryCache).Verifiable(); Assert.AreEqual(0, memoryCache.GetCount()); memoryCache.Add(fk1, new MemoryCacherTests.One(), new CacheItemPolicy()); memoryCache.Add(fk2, new MemoryCacherTests.One(), new CacheItemPolicy()); Assert.AreEqual(2, memoryCache.Count()); new CacheCleaner(_objectCacheFactory.Object).Clean(); Assert.AreEqual(0, memoryCache.GetCount()); }
internal long CacheManagerThread(int minPercent) { if (Interlocked.Exchange(ref _inCacheManagerThread, 1) != 0) { return(0); } try { if (_disposed == 1) { return(0); } #if DEBUG Dbg.Trace("MemoryCacheStats", "**BEG** CacheManagerThread " + DateTime.Now.ToString("T", CultureInfo.InvariantCulture)); #endif // The timer thread must always call Update so that the CacheManager // knows the size of the cache. Update(); AdjustTimer(); int percent = Math.Max(minPercent, GetPercentToTrim()); long beginTotalCount = _memoryCache.GetCount(); Stopwatch sw = Stopwatch.StartNew(); long trimmedOrExpired = _memoryCache.Trim(percent); sw.Stop(); // 1) don't update stats if the trim happend because MAX_COUNT was exceeded // 2) don't update stats unless we removed at least one entry if (percent > 0 && trimmedOrExpired > 0) { SetTrimStats(sw.Elapsed.Ticks, beginTotalCount, trimmedOrExpired); } #if DEBUG Dbg.Trace("MemoryCacheStats", "**END** CacheManagerThread: " + ", percent=" + percent + ", beginTotalCount=" + beginTotalCount + ", trimmed=" + trimmedOrExpired + ", Milliseconds=" + sw.ElapsedMilliseconds); #endif #if PERF Debug.WriteLine("CacheCommon.CacheManagerThread:" + " minPercent= " + minPercent + ", percent= " + percent + ", beginTotalCount=" + beginTotalCount + ", trimmed=" + trimmedOrExpired + ", Milliseconds=" + sw.ElapsedMilliseconds + "\n"); #endif return(trimmedOrExpired); } finally { Interlocked.Exchange(ref _inCacheManagerThread, 0); } }
/// <summary> /// Stores an object identified by a unique key in cache. /// </summary> /// <param name="correlationId"></param> /// <param name="key">Unique key identifying a data object.</param> /// <param name="value">The data object to store.</param> /// <param name="timeout">Time to live for the object in milliseconds.</param> public async Task <object> StoreAsync(string correlationId, string key, object value, long timeout) { if (key == null) { throw new ArgumentNullException(nameof(key)); } // Shortcut to remove entry from the cache if (value == null) { if (_standardCache.Contains(key)) { _standardCache.Remove(key); } return(null); } if (MaxSize <= _standardCache.GetCount()) { lock (_lock) { if (MaxSize <= _standardCache.GetCount()) { _standardCache.Trim(5); } } } timeout = timeout > 0 ? timeout : Timeout; _standardCache.Set(key, value, new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMilliseconds(timeout) }); return(await Task.FromResult(value)); }
public void TestCount() { MemoryCache memoryCount = new MemoryCache("count"); Desenvolvedor dev = new Desenvolvedor(); dev.Nome = "Ninja"; dev.Linguagem = "C#"; dev.AnosExperiencia = 15; CacheItemPolicy policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(2); memoryCount.Add("devRemove", dev, policy); Assert.AreEqual(1, memoryCount.GetCount()); }
public void Trim () { var config = new NameValueCollection (); config ["__MonoEmulateOneCPU"] = "true"; var mc = new MemoryCache ("MyCache", config); for (int i = 0; i < 10; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), null); // .NET doesn't touch the freshest 10 entries Assert.AreEqual (10, mc.GetCount (), "#A1-1"); long trimmed = mc.Trim (50); Assert.AreEqual (0, trimmed, "#A1-2"); Assert.AreEqual (10, mc.GetCount (), "#A1-3"); mc = new MemoryCache ("MyCache", config); // Only entries 11- are considered for removal for (int i = 0; i < 11; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), null); Assert.AreEqual (11, mc.GetCount (), "#A2-1"); trimmed = mc.Trim (50); Assert.AreEqual (1, trimmed, "#A2-2"); Assert.AreEqual (10, mc.GetCount (), "#A2-3"); mc = new MemoryCache ("MyCache", config); // Only entries 11- are considered for removal for (int i = 0; i < 125; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), null); Assert.AreEqual (125, mc.GetCount (), "#A3-1"); trimmed = mc.Trim (50); Assert.AreEqual (62, trimmed, "#A3-2"); Assert.AreEqual (63, mc.GetCount (), "#A3-3"); // Testing the removal order mc = new MemoryCache ("MyCache", config); var removed = new List <string> (); var cip = new CacheItemPolicy (); cip.RemovedCallback = (CacheEntryRemovedArguments args) => { removed.Add (args.CacheItem.Key); }; for (int i = 0; i < 50; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), cip); object value; for (int i = 0; i < 50; i++) value = mc.Get ("key" + i.ToString ()); trimmed = mc.Trim (50); Assert.AreEqual (25, mc.GetCount (), "#A4-1"); Assert.AreEqual (25, trimmed, "#A4-2"); Assert.AreEqual (25, removed.Count, "#A4-3"); // OK, this is odd... The list is correct in terms of entries removed but the entries // are removed in the _MOST_ frequently used order, within the group selected for removal. for (int i = 24; i >= 0; i--) { int idx = 24 - i; Assert.AreEqual ("key" + i.ToString (), removed [idx], "#A5-" + idx.ToString ()); } }
internal long CacheManagerThread(int minPercent) { if (Interlocked.Exchange(ref _inCacheManagerThread, 1) != 0) { return(0); } try { if (_disposed == 1) { return(0); } Dbg.Trace("MemoryCacheStats", "**BEG** CacheManagerThread " + DateTime.Now.ToString("T", CultureInfo.InvariantCulture)); // The timer thread must always call Update so that the CacheManager // knows the size of the cache. Update(); AdjustTimer(); int percent = Math.Max(minPercent, GetPercentToTrim()); long beginTotalCount = _memoryCache.GetCount(); long trimmedOrExpired = 0; Stopwatch sw = new Stopwatch(); // There is a small window here where the cache could be empty, but percentToTrim is > 0. // In this case, it makes no sense to trim, and in fact causes a divide-by-zero exception. // See - https://github.com/dotnet/runtime/issues/1423 if (percent > 0 && beginTotalCount > 0) { sw.Start(); trimmedOrExpired = _memoryCache.Trim(percent); sw.Stop(); // 1) don't update stats if the trim happend because MAX_COUNT was exceeded // 2) don't update stats unless we removed at least one entry if (percent > 0 && trimmedOrExpired > 0) { SetTrimStats(sw.Elapsed.Ticks, beginTotalCount, trimmedOrExpired); } } Dbg.Trace("MemoryCacheStats", "**END** CacheManagerThread: " + ", percent=" + percent + ", beginTotalCount=" + beginTotalCount + ", trimmed=" + trimmedOrExpired + ", Milliseconds=" + sw.ElapsedMilliseconds); #if PERF Debug.WriteLine("CacheCommon.CacheManagerThread:" + " minPercent= " + minPercent + ", percent= " + percent + ", beginTotalCount=" + beginTotalCount + ", trimmed=" + trimmedOrExpired + ", Milliseconds=" + sw.ElapsedMilliseconds + Environment.NewLine); #endif return(trimmedOrExpired); } catch (ObjectDisposedException) { // There is a small window for _memoryCache to be disposed after we check our own // disposed bit. No big deal. return(0); } finally { Interlocked.Exchange(ref _inCacheManagerThread, 0); } }
public void TestCacheSliding () { var config = new NameValueCollection (); config["cacheMemoryLimitMegabytes"] = 0.ToString (); config["physicalMemoryLimitPercentage"] = 100.ToString (); config["__MonoEmulateOneCPU"] = true.ToString (); // it appears that pollingInterval does nothing, so we set the Mono timer as well config["pollingInterval"] = new TimeSpan (0, 0, 1).ToString (); config["__MonoTimerPeriod"] = 1.ToString (); using (var mc = new MemoryCache ("TestCacheSliding", config)) { Assert.AreEqual (0, mc.GetCount (), "#CSL1"); var cip = new CacheItemPolicy(); cip.SlidingExpiration = new TimeSpan (0, 0, 1); mc.Add("slidingtest", "42", cip); mc.Add("expire1", "1", cip); mc.Add("expire2", "2", cip); mc.Add("expire3", "3", cip); mc.Add("expire4", "4", cip); mc.Add("expire5", "5", cip); Assert.AreEqual (6, mc.GetCount (), "#CSL2"); for (int i = 0; i < 50; i++) { global::System.Threading.Thread.Sleep (100); var item = mc.Get ("slidingtest"); Assert.AreNotEqual (null, item, "#CSL3-" + i); } Assert.AreEqual (1, mc.GetCount (), "#CSL4"); global::System.Threading.Thread.Sleep (4 * 1000); Assert.AreEqual (0, mc.GetCount (), "#CSL5"); } }
public void TestCacheExpiryOrdering () { var config = new NameValueCollection (); config["cacheMemoryLimitMegabytes"] = 0.ToString (); config["physicalMemoryLimitPercentage"] = 100.ToString (); config["__MonoEmulateOneCPU"] = true.ToString (); // it appears that pollingInterval does nothing, so we set the Mono timer as well config["pollingInterval"] = new TimeSpan (0, 0, 1).ToString (); config["__MonoTimerPeriod"] = 1.ToString (); using (var mc = new MemoryCache ("TestCacheExpiryOrdering", config)) { Assert.AreEqual (0, mc.GetCount (), "#CEO1"); // add long lived items into the cache first for (int i = 0; i < 100; i++) { var cip = new CacheItemPolicy (); cip.SlidingExpiration = new TimeSpan (0, 0, 10); mc.Add ("long-" + i, i, cip); } Assert.AreEqual (100, mc.GetCount (), "#CEO2"); // add shorter lived items into the cache, these should expire first for (int i = 0; i < 100; i++) { var cip = new CacheItemPolicy (); cip.SlidingExpiration = new TimeSpan(0, 0, 1); mc.Add ("short-" + i, i, cip); } Assert.AreEqual (200, mc.GetCount (), "#CEO3"); global::System.Threading.Thread.Sleep (4 * 1000); Assert.AreEqual (100, mc.GetCount (), "#CEO4"); } }
public void TestExpiredGetValues () { var config = new NameValueCollection (); config["cacheMemoryLimitMegabytes"] = 0.ToString (); config["physicalMemoryLimitPercentage"] = 100.ToString (); config["__MonoEmulateOneCPU"] = true.ToString (); // it appears that pollingInterval does nothing, so we set the Mono timer as well config["pollingInterval"] = new TimeSpan (0, 0, 10).ToString (); config["__MonoTimerPeriod"] = 10.ToString (); using (var mc = new MemoryCache ("TestExpiredGetValues", config)) { Assert.AreEqual (0, mc.GetCount (), "#EGV1"); var keys = new List<string> (); // add some short duration entries for (int i = 0; i < 10; i++) { var key = "short-" + i; var expireAt = DateTimeOffset.Now.AddSeconds (1); mc.Add (key, i.ToString (), expireAt); keys.Add (key); } Assert.AreEqual (10, mc.GetCount (), "#EGV2"); global::System.Threading.Thread.Sleep (1000); // we have waited but the items won't be expired by the timer since it wont have fired yet Assert.AreEqual (10, mc.GetCount (), "#EGV3"); // calling GetValues() will expire the items since we are now past their expiresAt mc.GetValues (keys); Assert.AreEqual (0, mc.GetCount (), "#EGV4"); } }
public void TestCacheShrink () { const int HEAP_RESIZE_THRESHOLD = 8192 + 2; const int HEAP_RESIZE_SHORT_ENTRIES = 2048; const int HEAP_RESIZE_LONG_ENTRIES = HEAP_RESIZE_THRESHOLD - HEAP_RESIZE_SHORT_ENTRIES; var config = new NameValueCollection (); config["cacheMemoryLimitMegabytes"] = 0.ToString (); config["physicalMemoryLimitPercentage"] = 100.ToString (); config["__MonoEmulateOneCPU"] = true.ToString (); // it appears that pollingInterval does nothing, so we set the Mono timer as well config["pollingInterval"] = new TimeSpan (0, 0, 1).ToString (); config["__MonoTimerPeriod"] = 1.ToString (); using (var mc = new MemoryCache ("TestCacheShrink", config)) { Assert.AreEqual (0, mc.GetCount (), "#CS1"); // add some short duration entries for (int i = 0; i < HEAP_RESIZE_SHORT_ENTRIES; i++) { var expireAt = DateTimeOffset.Now.AddSeconds (3); mc.Add ("short-" + i, i.ToString (), expireAt); } Assert.AreEqual (HEAP_RESIZE_SHORT_ENTRIES, mc.GetCount (), "#CS2"); // add some long duration entries for (int i = 0; i < HEAP_RESIZE_LONG_ENTRIES; i++) { var expireAt = DateTimeOffset.Now.AddSeconds (12); mc.Add ("long-" + i, i.ToString (), expireAt); } Assert.AreEqual (HEAP_RESIZE_LONG_ENTRIES + HEAP_RESIZE_SHORT_ENTRIES, mc.GetCount(), "#CS3"); // wait for the cache thread to expire the short duration items, this will also shrink the size of the cache global::System.Threading.Thread.Sleep (5 * 1000); Assert.AreEqual (HEAP_RESIZE_LONG_ENTRIES, mc.GetCount (), "#CS4"); // add some new items into the cache, this will grow the cache again for (int i = 0; i < HEAP_RESIZE_LONG_ENTRIES; i++) { mc.Add("final-" + i, i.ToString (), DateTimeOffset.Now.AddSeconds (4)); } Assert.AreEqual (HEAP_RESIZE_LONG_ENTRIES + HEAP_RESIZE_LONG_ENTRIES, mc.GetCount (), "#CS5"); } }
public void TestCacheSliding () { var config = new NameValueCollection (); config["cacheMemoryLimitMegabytes"] = 0.ToString (); config["physicalMemoryLimitPercentage"] = 100.ToString (); config["pollingInterval"] = new TimeSpan (0, 0, 1).ToString (); using (var mc = new MemoryCache ("TestCacheSliding", config)) { Assert.AreEqual (0, mc.GetCount (), "#CSL1"); var cip = new CacheItemPolicy(); // The sliding expiration timeout has to be greater than 1 second because // .NET implementation ignores timeouts updates smaller than // CacheExpires.MIN_UPDATE_DELTA which is equal to 1. cip.SlidingExpiration = new TimeSpan (0, 0, 2); mc.Add("slidingtest", "42", cip); mc.Add("expire1", "1", cip); mc.Add("expire2", "2", cip); mc.Add("expire3", "3", cip); mc.Add("expire4", "4", cip); mc.Add("expire5", "5", cip); Assert.AreEqual (6, mc.GetCount (), "#CSL2"); for (int i = 0; i < 50; i++) { global::System.Threading.Thread.Sleep (100); var item = mc.Get ("slidingtest"); Assert.AreNotEqual (null, item, "#CSL3-" + i); } Assert.IsNull (mc.Get ("expire1"), "#CSL4-1"); Assert.IsNull (mc.Get ("expire2"), "#CSL4-2"); Assert.IsNull (mc.Get ("expire3"), "#CSL4-3"); Assert.IsNull (mc.Get ("expire4"), "#CSL4-4"); Assert.IsNull (mc.Get ("expire5"), "#CSL4-5"); Assert.AreEqual (1, mc.GetCount (), "#CSL4"); global::System.Threading.Thread.Sleep (4 * 1000); Assert.IsNull (mc.Get ("slidingtest"), "#CSL5a"); Assert.AreEqual (0, mc.GetCount (), "#CSL5"); } }
public void Trim () { var config = new NameValueCollection (); config ["__MonoEmulateOneCPU"] = "true"; var mc = new MemoryCache ("MyCache", config); for (int i = 0; i < 10; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), null); Assert.AreEqual (10, mc.GetCount (), "#A1-1"); long trimmed = mc.Trim (50); Assert.AreEqual (5, trimmed, "#A1-2"); Assert.AreEqual (5, mc.GetCount (), "#A1-3"); mc = new MemoryCache ("MyCache", config); // Only entries 11- are considered for removal for (int i = 0; i < 11; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), null); Assert.AreEqual (11, mc.GetCount (), "#A2-1"); trimmed = mc.Trim (50); Assert.AreEqual (6, trimmed, "#A2-2"); Assert.AreEqual (5, mc.GetCount (), "#A2-3"); mc = new MemoryCache ("MyCache", config); // Only entries 11- are considered for removal for (int i = 0; i < 125; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), null); Assert.AreEqual (125, mc.GetCount (), "#A3-1"); trimmed = mc.Trim (50); Assert.AreEqual (63, trimmed, "#A3-2"); Assert.AreEqual (62, mc.GetCount (), "#A3-3"); // Testing the removal order mc = new MemoryCache ("MyCache", config); var removed = new List <string> (); var cip = new CacheItemPolicy (); cip.RemovedCallback = (CacheEntryRemovedArguments args) => { removed.Add (args.CacheItem.Key); }; for (int i = 0; i < 50; i++) mc.Set ("key" + i.ToString (), "value" + i.ToString (), cip); object value; for (int i = 0; i < 50; i++) value = mc.Get ("key" + i.ToString ()); trimmed = mc.Trim (50); Assert.AreEqual (25, mc.GetCount (), "#A4-1"); Assert.AreEqual (25, trimmed, "#A4-2"); Assert.AreEqual (25, removed.Count, "#A4-3"); for (int i = 0; i < 25; i++) Assert.AreEqual ("key" + i.ToString (), removed [i], "#A5-" + i.ToString ()); }