MemoryCache yapılandırma itaat bellek sınırlarını değil
İle çalışıyorum .NET bir uygulama 4.0 MemoryCache sınıf ve en fazla önbellek boyutunu sınırlamak için çalışıyor, ama benim testlerde önbellek aslında sınırları biat görünmüyor.
, according to MSDN, önbellek boyutu sınırı olması gereken: ayarlar kullanıyorum
- CacheMemoryLimitMegabytes: maksimum bellek bir nesne örneği büyüyebileceği megabayt olarak boyutu."
- PhysicalMemoryLimitPercentage:"Önbelleği kullanabilir fiziksel bellek yüzdesi, 100 ila 1 arasında bir tamsayı değeri olarak ifade edilir. Varsayılan gösterir, sıfırdırMemoryCacheörnekleri kendi belleği yönetmek1bellek miktarına göre bilgisayarda yüklü."1.Bu herhangi bir değer ve 4 ile göz ardı yerini tamamen doğru değil.
Bu değerler önbelleği her x saniye ateş temizler ve aynı zamanda yoklama aralığı ve diğer belgesiz değişkenler bağımlı olan iplik gibi, yaklaşık olarak değil, sabit sınırları olduğunu anlıyorum. Ancak hesaba bile bu sapmalar alarak, ilk öğeyi ayarladıktan sonra önbellekten tahliye edilirken çılgınca tutarsız önbellek boyutlarını görüyorumCacheMemoryLimitMegabytesvePhysicalMemoryLimitPercentagebirlikte ya da bir test uygulaması tek başına. Her test yaptım emin olmak için 10 kere ve hesaplanan ortalama rakam.
Bu aşağıdaki örnek kodu 3 GB RAM ile 32 bit Windows 7 PC üzerinde test sonuçları. Önbellek boyutu ilk görüşme için alınır() CacheİtemRemovedher testte. (Önbellek gerçek boyutu bu daha büyük olacak farkındayım)
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
Burada test uygulama:
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");
}
}
}
NedenMemoryCacheitaat yapılandırılmış bellek sınırı değil mi?
CEVAP
Vay be, ben sadece tamamen çok fazla zaman etrafında reflektör ile CLR kazma harcadı, ama sonunda iyi burada neler oluyor idare ediyorsun bence.
Ayarları doğru okunan, ancak bir bellek sınırı ayarı aslında işe yaramaz hale gelecek gibi görünüyor CLR kendi içinde derin bir sorun var.
Aşağıdaki kod Sistemine yansıtılır.Çalışma zamanı.Önbellekleme DLL, CacheMemoryMonitor sınıfı için (diğer ayar ile fiziksel bellek ve fırsatlar izler benzer bir durum var, ama bu daha önemli olanıdır):
protected override int GetCurrentPressure()
{
int num = GC.CollectionCount(2);
SRef ref2 = this._sizedRef;
if ((num != this._gen2Count) && (ref2 != null))
{
this._gen2Count = num;
this._idx ^= 1;
this._cacheSizeSampleTimes[this._idx] = DateTime.UtcNow;
this._cacheSizeSamples[this._idx] = ref2.ApproximateSize;
IMemoryCacheManager manager = s_memoryCacheManager;
if (manager != null)
{
manager.UpdateCacheSize(this._cacheSizeSamples[this._idx], this._memoryCache);
}
}
if (this._memoryLimit <= 0L)
{
return 0;
}
long num2 = this._cacheSizeSamples[this._idx];
if (num2 > this._memoryLimit)
{
num2 = this._memoryLimit;
}
return (int) ((num2 * 100L) / this._memoryLimit);
}
İlk şey olabilir olduğunu fark etmez bile denemek büyüklüğüne bakın önbellek kadar sonra bir Gen2 çöp toplama yerine sadece düşen arkasındaki varolan saklı boyutu değeri cacheSizeSamples. Hiç hedef sağ vurmak mümkün olmayacak, ama eğer geri kalan çalışsaydı en azından gerçek bir sorunumuz var önce boyutunu bir ölçüm elde ederiz.
Gen2 bir GC varsayarak oluştu yani sorun bu ref2 2, kaçıyoruz.ApproximateSize aslında önbellek boyutu yaklaşan korkunç bir iş yok. CLR önemsiz ben aracılığıyla Slogging bu bir Sistem bulundu.SizedReference, ve bu değeri elde etmek için ne yaptığını (IntPtr bir kolu MemoryCache kendisi nesne):
[SecurityCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern long GetApproximateSizeOfSizedRef(IntPtr h);
Dış bildirimi Bu noktada yönetilmeyen windows toprak içine dalış gider anlamına geldiğini varsayıyorum, ve orada ne yaptığını bulmaya başlaması için nasıl hiçbir fikrim yok. Çalışırken korkunç bir iş yok ama gözlemlediğim kadarıyla genel olarak o şeyin büyüklüğü yaklaşık.
Üçüncü dikkat çeken şey orada yöneticisi çağrısı.Bir şeyler yapmak gerekir gibi geliyor UpdateCacheSize. Bu s_memoryCacheManager nasıl olması gerektiğiyle ilgili herhangi normal bir örnek ne yazık ki her zaman boş olacaktır. Alan public static üye ObjectCache ayarlanır.Ana. Bu maruz kalan kullanıcı için karışıklık olursa o kadar seçer, ve ben gerçekten yapar bu şeyin iş olması gerektiği gibi benzeyen ile birlikte benim kendi İMemoryCacheManager uygulama, ayar için ObjectCache.Ev sahibi, ve sonra örnek çalışan. Bu noktada olsa da, göründüğü gibi belki de sadece kendi önbellek uygulaması bile rahatsız olan tüm bu şeyler, özellikle bu yana hiçbir fikrim yok eğer ayarını kendi sınıfı için ObjectCache.(Dışarıda bir süreç olabilir bunların hepsi etkiler yani statik) önbellek ölçmek için ana kadar başka şeylere zarar verebilir.
En azından bu birkaç parça durumunda bir parçası sadece dik bir hata olduğuna inanmak istiyorum. Anlaşma bu şey ile ne MS birinden duymak iyi olurdu.
Bu dev cevap TLDR version: CacheMemoryLimitMegabytes bu noktada tamamen bozuk olduğunu Varsayalım. 10 MB olarak ayarlayın ve ~2 GB önbelleği doldurup maddenin kaldırılması hiç açma ile bellek özel bir patlatmaya devam edin.
Java 5'te neden uçucu değil't sen...
Çözüm Yapılandırma ama VS2010 Araç Pla...
Bir bellek sızıntısı bir MemoryStream ...
Nasıl yapılandırma programı kullanmada...
Çözmek için nasıl "Eklenti yürütm...