2015-08-08 13 views
6

System.Runtime.Caching.MemoryCache .NET Framework'teki (sürüm 4+) sınıfında nesneleri bellek olarak önbelleğe alan ve anahtar olarak anahtar kullanan bir sınıftır. System.Collections.Generic.Dictionary<string, object>'dan daha fazla olan bu sınıf, önbelleklerin ne kadar büyük büyüyebileceğini (mutlak veya göreli olarak) yapılandırabilmenizi, farklı önbellek öğeleri için farklı son kullanma politikaları belirleyebilmenizi ve daha fazlasını yapabilmenizi sağlar.MemoryCache'ın bellek sınırları tam olarak ne anlama geliyor?

Sorularım bellek sınırlarıyla ilgilidir. MSDN'deki dokümanların hiçbiri bunu tatmin edici bir şekilde açıklamıyor gibi görünüyor ve Referans Kaynağı'ndaki kod oldukça opaktır. Tüm bunları bir "soru" haline getirdiğim için üzgünüm, ama kendi sorularına nasıl cevap vereceğimi anlayamıyorum, çünkü bunlar sadece genel bir sorunun farklı görünümleridir: "deyimsel C# ile nasıl uzlaşırsınız? /.NET, neredeyse tamamen yönetilen kodla yapılandırılabilen, yapılandırılabilir bellek sınırlarına sahip, genellikle kullanışlı bir bellek içi önbellek kavramıyla? "

  1. Anahtar boyutları, MemoryCache'ın ele almayı düşündüğü alana doğru sayılıyor mu? Dahili havuzdaki tuşlara ne olur, her biri önbellek boyutuna sadece bir nesne referansının boyutunu eklemelidir?
  2. MemoryCache, havuzda depolanan nesnenin boyutunu belirlerken depoladığı nesne referanslarının boyutundan daha fazlasını mu düşünüyor? Demek istediğim, doğru mu? Aksi takdirde, konfigürasyon seçenekleri genel durum için son derece yanıltıcıdır ... kalan sorular için, bunun olduğunu varsayacağım.
  3. MemoryCache öğesinin, önbellekte saklanan değerlerin nesne referanslarının boyutundan neredeyse fazlasını dikkate aldığı göz önünde bulundurulduğunda, ne kadar derine gidiyor?
    1. Böyle bir şey uygulayan olsaydı, bunu çok zor da "üst" referans özelliklerinde çekerek olmadan, bireysel nesnelerin "çocuk" üyelerinin bellek kullanımını dikkate almak bulur. Örneğin, oyun uygulamasında bir sınıf hayal et, Player. Player, oyuncunun hangi yöne baktığını, kaç tane dişli çark tuttuğunu vb. Kapsülleyen public PlayerStateData PlayerState { get; } özelliğinde kapsanan oyuncuya özel bir duruma sahiptir. Ayrıca, tüm oyunun durumu için geçerli olan public GameStateData GameState { get; } Sadece bir oyuncuyu bilen bir yöntemden oyunun (daha büyük) durumuna geri dönün.
    2. Bellek Önbelleği, önbellek katkısının boyutu göz önünde bulundurulduğunda hem PlayerState hem de GameState'u düşünüyor mu?
    3. Belki de "doğrudan önbellekte saklanan nesneler tarafından alınan yönetilen yığın üzerinde toplam boyutu nedir ve bu nesnelerin üyeleri aracılığıyla erişilebilen her şey" gibi daha fazladır?
    4. GameState'un katkısını 5'e kadar sınırladığınız katkının 5 katına çıkarılması aptalca olacaktır. Fakat yine de, olası bir uygulama bunu yapabilir ve sayılması zor GameState sayılmadan PlayerState.
  4. Bir nesne MemoryCache'de birden çok kez depolanıyorsa, her bir giriş ayrı olarak sınırlara mı sayılır?
  5. Bir öncekiyle ilgili olarak, bir nesne doğrudan MemoryCache'de, aynı zamanda başka bir nesnenin üyeleri aracılığıyla dolaylı olarak depolanıyorsa, birinin bellek sınırında ne gibi bir etkisi vardır?
  6. Bir nesne MemoryCache'de depolanırsa, aynı zamanda MemoryCache'den tamamen ayrılmış bazı başka canlı nesneler tarafından da başvuruda bulunularak, hangi nesneler bellek sınırına göre sayılır? Peki, dışardan gelen dış referanslara sahip bazı (ama hepsi değil) bir dizi nesne mi?

Kendi araştırmam daha sonra here açar, here aldıktan sonra anlamaya çalışan vazgeçti SRef.cs, götürdü. Tüm bu soruların cevaplarını tahmin etmek, sonuçta bu tanıtıcıda saklanan INT64'ü dolduran kodun bulunması ve meditasyon etrafında dönecektir.

+0

IMC, MemoryCache'in sınırlama işleminin en kullanışlı uygulaması, önbelleğin soruyu mükemmel bir şekilde yanıtlayabilmesini gerektirebilir; "temizlendiyse ve tam bir GC hemen sonra çalıştırılırsa, bu GC çalışması sırasında kaç bayt bellek boşalır? ?" Ancak bu konu hakkında daha fazla düşünürsek, önbellek sahibi açıklanmamış bir (veya en azından çözülemez) kurallara uymazsa, cevabının ağır bir şekilde şişirilmesini beklerim. teorik nedenler. –

+0

Buraya, özellikle de paylaşılan devlete yapılan atıflarla ilgili olarak tam olarak aynı soruları sormak için geldim. Başka bir soru da beni rahatsız ediyor ... önbelleğe alınmış nesnenin (grafik) önbellekte yerleştirildikten sonra büyür ya da küçülür ...? Her şey çok belirsiz. – spender

cevap

1

Geç olduğunu biliyorum ama neler olduğunu anlamaya çalışmak için kaynak kodda çok fazla kazım yaptım ve şimdi oldukça iyi bir fikrim var. MemoryCache'ın MSDN üzerinde en kötü belgelendirilmiş sınıf olduğunu söyleyeceğim, hangi tür uygulamaların optimize edilmesine çalışan insanlar tarafından kullanılması amaçlanan bir şey için beni şaşırtıyor.

MemoryCache, nesnelerin boyutunu ölçmek için özel "boyutlu referans" kullanır. Bu, "System.SizedReference" adı verilen dahili bir türü sarmak için yansımayı içeren bellek önbellek kaynak kodundaki devasa bir hacke benziyor. Bu, GC'nin gen 2 sırasında işaret ettiği nesne grafiğinin boyutunu ayarlamasına neden olduğunu söyleyebilirim. koleksiyonları.

Testlerimden, bu, üst nesnelerin boyutlarını ve böylece üst nesneler tarafından başvurulan tüm alt nesneleri de içerecektir. ANCAK, ana nesnelere başvurularda zayıf referanslar yaparsanız (ör. WeakReference veya WeakReference<> aracılığıyla) sonra artık nesne grafiğinin bir parçası olarak sayılmaz, bu yüzden şimdi tüm önbellek nesneleri için yaptığım şeydir.

Önbellek nesnelerinin tamamen kendi kendine yeten olması veya bellek sınırlaması için diğer nesneler için zayıf referanslar kullanması gerektiğine inanıyorum.

Eğer kendi kendinizle oynamak isterseniz, kodu SRef.cs'dan kopyalayın, bir nesne grafiği oluşturun ve yeni bir SRef örneğini işaret edin ve ardından GC.Collect'i arayın. Koleksiyondan sonra, yaklaşık boyut, nesne grafiğinin boyutuna ayarlanacaktır.