Note that there are some explanatory texts on larger screens.

plurals
  1. POMemoryCache does not obey memory limits in configuration
    primarykey
    data
    text
    <p>I’m working with the .NET 4.0 <a href="http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache(v=vs.110).aspx" rel="noreferrer"><strong>MemoryCache</strong></a> class in an application and trying to limit the maximum cache size, but in my tests it does not appear that the cache is actually obeying the limits. </p> <p>I'm using the settings which, <a href="http://msdn.microsoft.com/en-us/library/system.runtime.caching.configuration.memorycacheelement(v=vs.110).aspx" rel="noreferrer" title="MSDN: MemoryCacheElement">according to MSDN</a>, are supposed to limit the cache size:</p> <blockquote> <ol> <li><a href="http://msdn.microsoft.com/en-us/library/system.runtime.caching.configuration.memorycacheelement.cachememorylimitmegabytes(v=vs.110).aspx" rel="noreferrer"><strong>CacheMemoryLimitMegabytes</strong></a>: The maximum memory size, in megabytes, that an instance of an object can grow to."</li> <li><strong><a href="http://msdn.microsoft.com/en-us/library/system.runtime.caching.configuration.memorycacheelement.physicalmemorylimitpercentage(v=vs.110).aspx" rel="noreferrer">PhysicalMemoryLimitPercentage</a>:</strong> "The percentage of physical memory that the cache can use, expressed as an integer value from 1 to 100. The default is zero, which indicates that <strong>MemoryCache</strong> instances manage their own memory<sup><b>1</b></sup> based on the amount of memory that is installed on the computer." <sup><b>1.</b> This is not entirely correct-- any value below 4 is ignored and replaced with 4.</sup></li> </ol> </blockquote> <p>I understand that these values are approximate and not hard limits as the thread that purges the cache is fired every x seconds and is also dependent on the polling interval and other undocumented variables. However even taking into account these variances, I'm seeing wildly inconsistent cache sizes when the first item is being evicted from the cache after setting <strong>CacheMemoryLimitMegabytes</strong> and <strong>PhysicalMemoryLimitPercentage</strong> together or singularly in a test app. To be sure I ran each test 10 times and calculated the average figure.</p> <p>These are the results of testing the example code below on a 32-bit Windows 7 PC with 3GB of RAM. Size of the cache is taken after the first call to <strong>CacheItemRemoved()</strong> on each test. (I am aware the actual size of cache will be larger than this)</p> <pre class="lang-cs prettyprint-override"><code>MemLimitMB MemLimitPct AVG Cache MB on first expiry 1 NA 84 2 NA 84 3 NA 84 6 NA 84 NA 1 84 NA 4 84 NA 10 84 10 20 81 10 30 81 10 39 82 10 40 79 10 49 146 10 50 152 10 60 212 10 70 332 10 80 429 10 100 535 100 39 81 500 39 79 900 39 83 1900 39 84 900 41 81 900 46 84 900 49 1.8 GB approx. in task manager no mem errros 200 49 156 100 49 153 2000 60 214 5 60 78 6 60 76 7 100 82 10 100 541 </code></pre> <p>Here is the test application:</p> <pre class="lang-cs prettyprint-override"><code>using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Runtime.Caching; using System.Text; namespace FinalCacheTest { internal class Cache { private Object Statlock = new object(); private int ItemCount; private long size; private MemoryCache MemCache; private CacheItemPolicy CIPOL = new CacheItemPolicy(); public Cache(long CacheSize) { CIPOL.RemovedCallback = new CacheEntryRemovedCallback(CacheItemRemoved); NameValueCollection CacheSettings = new NameValueCollection(3); CacheSettings.Add("CacheMemoryLimitMegabytes", Convert.ToString(CacheSize)); CacheSettings.Add("physicalMemoryLimitPercentage", Convert.ToString(49)); //set % here CacheSettings.Add("pollingInterval", Convert.ToString("00:00:10")); MemCache = new MemoryCache("TestCache", CacheSettings); } public void AddItem(string Name, string Value) { CacheItem CI = new CacheItem(Name, Value); MemCache.Add(CI, CIPOL); lock (Statlock) { ItemCount++; size = size + (Name.Length + Value.Length * 2); } } public void CacheItemRemoved(CacheEntryRemovedArguments Args) { Console.WriteLine("Cache contains {0} items. Size is {1} bytes", ItemCount, size); lock (Statlock) { ItemCount--; size = size - 108; } Console.ReadKey(); } } } namespace FinalCacheTest { internal class Program { private static void Main(string[] args) { int MaxAdds = 5000000; Cache MyCache = new Cache(1); // set CacheMemoryLimitMegabytes for (int i = 0; i &lt; MaxAdds; i++) { MyCache.AddItem(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); } Console.WriteLine("Finished Adding Items to Cache"); } } } </code></pre> <p>Why is <strong>MemoryCache</strong> not obeying the configured memory limits?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload