Je travaille avec la classe .NET 4.0 MemoryCache dans une application et j'essaie de limiter la taille maximale du cache, mais dans mes tests, il ne semble pas que le cache obéit réellement aux limites.
J'utilise les paramètres qui, selon MSDN , sont censés limiter la taille du cache:
- CacheMemoryLimitMegabytes : taille maximale de la mémoire, en mégaoctets, à laquelle une instance d'un objet peut atteindre. "
- PhysicalMemoryLimitPercentage : "Le pourcentage de mémoire physique que le cache peut utiliser, exprimé sous la forme d'un entier compris entre 1 et 100. La valeur par défaut est zéro, ce qui indique que lesinstances MemoryCache gèrent leur propre mémoire 1 en fonction de la quantité de mémoire installée sur le ordinateur." 1. Ce n'est pas tout à fait correct - toute valeur inférieure à 4 est ignorée et remplacée par 4.
Je comprends que ces valeurs sont approximatives et non des limites strictes car le thread qui purge le cache est déclenché toutes les x secondes et dépend également de l'intervalle d'interrogation et d'autres variables non documentées. Cependant, même en tenant compte de ces variations, je constate des tailles de cache extrêmement incohérentes lorsque le premier élément est expulsé du cache après avoir défini CacheMemoryLimitMegabytes et PhysicalMemoryLimitPercentage ensemble ou individuellement dans une application de test. Pour être sûr, j'ai exécuté chaque test 10 fois et calculé le chiffre moyen.
Voici les résultats du test de l'exemple de code ci-dessous sur un PC Windows 7 32 bits avec 3 Go de RAM. La taille du cache est prise après le premier appel à CacheItemRemoved () à chaque test. (Je suis conscient que la taille réelle du cache sera plus grande que cela)
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
Voici l'application de test:
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");
}
}
}
Pourquoi MemoryCache ne respecte- t- il pas les limites de mémoire configurées?