Pracuję z klasą .NET 4.0 MemoryCache w aplikacji i próbuję ograniczyć maksymalny rozmiar pamięci podręcznej, ale z moich testów nie wynika, że pamięć podręczna faktycznie przestrzega limitów.
Używam ustawień, które według MSDN mają ograniczać rozmiar pamięci podręcznej:
- CacheMemoryLimitMegabytes : maksymalna wielkość pamięci w megabajtach, do jakiej może wzrosnąć wystąpienie obiektu. "
- PhysicalMemoryLimitPercentage : "Procent pamięci fizycznej, której może używać pamięć podręczna, wyrażony jako liczba całkowita od 1 do 100. Wartość domyślna to zero, co oznacza, żeinstancje MemoryCache zarządzają własną pamięcią 1 na podstawie ilości pamięci zainstalowanej w komputer." 1. Nie jest to całkowicie poprawne - każda wartość poniżej 4 jest ignorowana i zastępowana 4.
Rozumiem, że te wartości są przybliżone i nie są twardymi limitami, ponieważ wątek, który czyści pamięć podręczną, jest uruchamiany co x sekund i jest również zależny od interwału sondowania i innych nieudokumentowanych zmiennych. Jednak nawet biorąc pod uwagę te wariancje, widzę szalenie niespójne rozmiary pamięci podręcznej, gdy pierwszy element jest eksmitowany z pamięci podręcznej po ustawieniu CacheMemoryLimitMegabytes i PhysicalMemoryLimitPercentage razem lub pojedynczo w aplikacji testowej. Dla pewności przeprowadziłem każdy test 10 razy i obliczyłem średnią wartość.
Oto wyniki testowania poniższego przykładowego kodu na 32-bitowym komputerze z systemem Windows 7 i 3 GB pamięci RAM. Rozmiar pamięci podręcznej jest pobierany po pierwszym wywołaniu CacheItemRemoved () w każdym teście. (Zdaję sobie sprawę, że rzeczywisty rozmiar pamięci podręcznej będzie większy niż ten)
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
Oto aplikacja testowa:
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");
}
}
}
Dlaczego MemoryCache nie przestrzega skonfigurowanych limitów pamięci?