private static void OvercapacityCompaction(MemoryCache cache) { CoherentState coherentState = cache._coherentState; // Clear() can update the reference in the meantime long currentSize = coherentState.Size; cache._logger.LogDebug($"Overcapacity compaction executing. Current size {currentSize}"); double?lowWatermark = cache._options.SizeLimit * (1 - cache._options.CompactionPercentage); if (currentSize > lowWatermark) { cache.Compact(currentSize - (long)lowWatermark, entry => entry.Size.Value, coherentState); } cache._logger.LogDebug($"Overcapacity compaction executed. New size {coherentState.Size}"); }
public void CompactLastAccessedRaceCondition() { const int numEntries = 100; MemoryCache cache = new MemoryCache(new MemoryCacheOptions()); Random random = new Random(); void FillCache() { for (int i = 0; i < numEntries; i++) { cache.Set($"key{i}", $"value{i}"); } } // start a few tasks to access entries in the background Task[] backgroundAccessTasks = new Task[Environment.ProcessorCount]; bool done = false; for (int i = 0; i < backgroundAccessTasks.Length; i++) { backgroundAccessTasks[i] = Task.Run(async() => { while (!done) { cache.TryGetValue($"key{random.Next(numEntries)}", out _); await Task.Yield(); } }); } for (int i = 0; i < 1000; i++) { FillCache(); cache.Compact(1); } done = true; Task.WaitAll(backgroundAccessTasks); }