SORU
1 AĞUSTOS 2011, PAZARTESİ


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

  1. CacheMemoryLimitMegabytes: maksimum bellek bir nesne örneği büyüyebileceği megabayt olarak boyutu."
  2. 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
11 EYLÜL 2011, Pazar


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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Andrew_Huang

    Andrew_Huang

    10 ŞUBAT 2006
  • sinumatic

    sinumatic

    19 Aralık 2006
  • JeezyVEVO

    JeezyVEVO

    12 Mayıs 2009