Estou trabalhando com a classe .NET 4.0 MemoryCache em um aplicativo e tentando limitar o tamanho máximo do cache, mas em meus testes não parece que o cache está realmente obedecendo aos limites.
Estou usando as configurações que, de acordo com o MSDN , devem limitar o tamanho do cache:
- CacheMemoryLimitMegabytes : O tamanho máximo da memória, em megabytes, que uma instância de um objeto pode atingir. "
- PhysicalMemoryLimitPercentage : "A porcentagem de memória física que o cache pode usar, expressa como um valor inteiro de 1 a 100. O padrão é zero, o que indica que as instâncias de MemoryCache gerenciam sua própria memória 1 com base na quantidade de memória instalada no computador." 1. Isso não está totalmente correto - qualquer valor abaixo de 4 é ignorado e substituído por 4.
Eu entendo que esses valores são aproximados e não limites rígidos, pois o thread que limpa o cache é disparado a cada x segundos e também depende do intervalo de pesquisa e de outras variáveis não documentadas. No entanto, mesmo levando em consideração essas variações, estou vendo tamanhos de cache totalmente inconsistentes quando o primeiro item está sendo removido do cache após definir CacheMemoryLimitMegabytes e PhysicalMemoryLimitPercentage juntos ou individualmente em um aplicativo de teste. Para ter certeza, executei cada teste 10 vezes e calculei o valor médio.
Estes são os resultados do teste do código de exemplo abaixo em um PC com Windows 7 de 32 bits com 3 GB de RAM. O tamanho do cache é obtido após a primeira chamada para CacheItemRemoved () em cada teste. (Estou ciente de que o tamanho real do cache será maior do que isso)
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
Aqui está o aplicativo de teste:
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 < MaxAdds; i++)
{
MyCache.AddItem(Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
}
Console.WriteLine("Finished Adding Items to Cache");
}
}
}
Por que o MemoryCache não está obedecendo aos limites de memória configurados?