Ich arbeite mit der .NET 4.0 MemoryCache- Klasse in einer Anwendung und versuche, die maximale Cache-Größe zu begrenzen. In meinen Tests scheint es jedoch nicht so zu sein, dass der Cache tatsächlich die Grenzwerte einhält.
Ich verwende die Einstellungen, die laut MSDN die Cache-Größe begrenzen sollen:
- CacheMemoryLimitMegabytes : Die maximale Speichergröße in Megabyte, auf die eine Instanz eines Objekts anwachsen kann. "
- PhysicalMemoryLimitPercentage : "Der Prozentsatz des physischen Speichers, den der Cache verwenden kann, ausgedrückt als ganzzahliger Wert von 1 bis 100. Der Standardwert ist Null. Dies gibt an, dass MemoryCache- Instanzen ihren eigenen Speicher 1 basierend auf derauf dem Computer installierten Speichermenge verwalten Computer." 1. Dies ist nicht ganz richtig - jeder Wert unter 4 wird ignoriert und durch 4 ersetzt.
Ich verstehe, dass diese Werte ungefähre und keine harten Grenzen sind, da der Thread, der den Cache löscht, alle x Sekunden ausgelöst wird und auch vom Abfrageintervall und anderen undokumentierten Variablen abhängt. Selbst unter Berücksichtigung dieser Abweichungen sehe ich wild inkonsistente Cache-Größen, wenn das erste Element aus dem Cache entfernt wird, nachdem CacheMemoryLimitMegabytes und PhysicalMemoryLimitPercentage zusammen oder einzeln in einer Test-App festgelegt wurden. Um sicherzugehen, habe ich jeden Test 10 Mal durchgeführt und die durchschnittliche Zahl berechnet.
Dies sind die Ergebnisse des Testens des folgenden Beispielcodes auf einem 32-Bit-Windows 7-PC mit 3 GB RAM. Die Größe des Caches wird nach dem ersten Aufruf von CacheItemRemoved () bei jedem Test übernommen. (Mir ist bekannt, dass die tatsächliche Größe des Caches größer sein wird)
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
Hier ist die Testanwendung:
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");
}
}
}
Warum hält MemoryCache die konfigurierten Speichergrenzen nicht ein?