MemoryCache ne respecte pas les limites de la mémoire de configuration

Je travaille avec le .NET 4.0 MemoryCache classe dans une application et d'essayer de limiter la taille maximale du cache, mais dans mes tests, il ne semble pas que le cache est en fait obéir les limites.

Je suis en utilisant les paramètres qui, selon MSDN, sont censés limiter la taille du cache:

  1. CacheMemoryLimitMegabytes: Le maximum de la taille de la mémoire, en mégaoctets, qu'une instance d'un objet peut se développer à."
  2. PhysicalMemoryLimitPercentage: "Le pourcentage de mémoire physique que le cache peut utiliser, exprimée comme une valeur entière de 1 à 100. La valeur par défaut est zéro, ce qui indique que MemoryCache instances de gérer leur propre mémoirele1 sur la base de la quantité de mémoire installée sur l'ordinateur." le1. 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 pas dur limites comme le fil qui purge le cache est tiré toutes les x secondes et est également dépendant de l'intervalle d'interrogation et d'autres sans-papiers variables. Cependant, même en tenant compte de ces écarts, je vais voir follement incohérentes tailles de cache lorsque le premier élément est supprimé du cache après la mise CacheMemoryLimitMegabytes et PhysicalMemoryLimitPercentage ensemble ou individuellement dans une application de test. Pour être sûr, j'ai couru chaque test 10 fois et calculé la moyenne.

Ce sont les résultats d'essais de l'exemple de code ci-dessous sur un 32 bits de Windows 7 PC avec 3 go de RAM. Taille de la mémoire cache est pris après le premier appel à CacheItemRemoved() sur chaque test. (Je suis conscient de la taille réelle de cache sera plus 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 le test de l'application:

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 est MemoryCache ne pas obéir à l'configuré les limites de la mémoire?

  • pour la boucle qui est mal ,sans i++
  • J'ai ajouté une connexion MS rapport de ce bug (peut-être que quelqu'un d'autre l'a déjà fait, mais bon...) connect.microsoft.com/VisualStudio/feedback/details/806334/...
  • Il est intéressant de noter que Microsoft a maintenant (comme de 9/2014) ajout d'une assez approfondie de réponse sur le connect billet ci-dessus. Le TLDR, c'est que MemoryCache ne pas intrinsèquement vérifier ces limites sur chaque opération, mais plutôt que les limites ne sont respectés lors de cache interne de parage, qui est périodique basée sur la dynamique interne des chronomètres.
  • Grâce Poussiéreux. Réponse intéressante à partir de MS sur la question.
  • Pouvez-vous nous éclairer sur les raisons d'utiliser "size = taille + (Nom.La Longueur + La Valeur.Longueur * 2);" et "size = taille - 108;"
  • Regarde comme ils ont mis à jour la documentation pour MemoryCache.CacheMemoryLimit: "MemoryCache ne pas appliquer instantanément CacheMemoryLimit chaque fois qu'un nouvel élément est ajouté à un MemoryCache instance. L'heuristique interne qui expulse des éléments supplémentaires de la MemoryCache t-il progressivement..." msdn.microsoft.com/en-us/library/...
  • Lien vers l'article ne semble pas correct...pouvez-vous résoudre ce problème?
  • Je pense que MSFT retiré de la question. En tout cas, MSFT fermé le problème après une discussion avec moi, où ils m'ont dit que la limite n'est appliquée après PoolingTime a expiré.

InformationsquelleAutor Canacourse | 2011-08-01