MemoryCache ไม่เป็นไปตามขีด จำกัด หน่วยความจำในการกำหนดค่า


87

ฉันกำลังทำงานกับคลาส. NET 4.0 MemoryCacheในแอปพลิเคชันและพยายาม จำกัด ขนาดแคชสูงสุด แต่ในการทดสอบของฉันไม่ปรากฏว่าแคชเป็นไปตามขีด จำกัด

ฉันใช้การตั้งค่าซึ่งตาม MSDNควร จำกัด ขนาดแคช:

  1. CacheMemoryLimitMegabytes : ขนาดหน่วยความจำสูงสุดเป็นเมกะไบต์ที่อินสแตนซ์ของวัตถุสามารถขยายได้ "
  2. PhysicalMemoryLimitPercentage : "เปอร์เซ็นต์ของหน่วยความจำฟิสิคัลที่แคชสามารถใช้ได้แสดงเป็นค่าจำนวนเต็มตั้งแต่ 1 ถึง 100 ค่าดีฟอลต์คือศูนย์ซึ่งบ่งชี้ว่าอินสแตนซ์ MemoryCacheจัดการหน่วยความจำ 1ของตนเองตามจำนวนหน่วยความจำที่ติดตั้งบน คอมพิวเตอร์." 1.สิ่งนี้ไม่ถูกต้องทั้งหมด - ค่าใด ๆ ที่ต่ำกว่า 4 จะถูกละเว้นและแทนที่ด้วย 4

ฉันเข้าใจว่าค่าเหล่านี้เป็นค่าโดยประมาณและไม่ใช่ข้อ จำกัด อย่างหนักเนื่องจากเธรดที่ล้างแคชจะเริ่มทำงานทุกๆ x วินาทีและยังขึ้นอยู่กับช่วงเวลาการสำรวจและตัวแปรอื่น ๆ ที่ไม่มีเอกสาร อย่างไรก็ตามแม้จะคำนึงถึงความแปรปรวนเหล่านี้ แต่ฉันก็เห็นขนาดแคชที่ไม่สอดคล้องกันอย่างมากเมื่อรายการแรกถูกขับออกจากแคชหลังจากตั้งค่าCacheMemoryLimitMegabytes และPhysicalMemoryLimitPercentageร่วมกันหรือเอกพจน์ในแอปทดสอบ เพื่อให้แน่ใจว่าฉันทำการทดสอบแต่ละครั้ง 10 ครั้งและคำนวณตัวเลขเฉลี่ย

นี่คือผลลัพธ์ของการทดสอบโค้ดตัวอย่างด้านล่างบนพีซี Windows 7 32 บิตที่มี RAM 3GB ขนาดของแคชถูกใช้หลังจากการเรียกครั้งแรกไปยังCacheItemRemoved ()ในการทดสอบแต่ละครั้ง (ฉันทราบว่าขนาดจริงของแคชจะใหญ่กว่านี้)

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

นี่คือแอปพลิเคชันทดสอบ:

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");
        }
    }
}

เหตุใดMemoryCache จึงไม่ปฏิบัติตามขีด จำกัด หน่วยความจำที่กำหนดไว้


2
สำหรับการวนซ้ำไม่ถูกต้องหากไม่มี i ++
xiaoyifang

4
ฉันได้เพิ่มรายงาน MS Connect สำหรับข้อบกพร่องนี้แล้ว (อาจมีคนอื่นทำไปแล้ว แต่อย่างไรก็ตาม ... ) connect.microsoft.com/VisualStudio/feedback/details/806334/…
Bruno Brant

3
เป็นที่น่าสังเกตว่าตอนนี้ Microsoft (ณ วันที่ 9/2014) ได้เพิ่มการตอบสนองอย่างละเอียดถี่ถ้วนเกี่ยวกับตั๋วเชื่อมต่อที่เชื่อมโยงด้านบน TLDR ของมันคือ MemoryCache ไม่ได้ตรวจสอบขีด จำกัด เหล่านี้โดยเนื้อแท้ในทุกการดำเนินการ แต่จะเคารพขีด จำกัด เฉพาะเมื่อการตัดแต่งแคชภายในซึ่งเป็นระยะตามตัวจับเวลาภายในแบบไดนามิก
ฝุ่น

5
ดูเหมือนว่าพวกเขาอัปเดตเอกสารสำหรับ MemoryCache.CacheMemoryLimit: "MemoryCache ไม่ได้บังคับใช้ CacheMemoryLimit ในทันทีทุกครั้งที่มีการเพิ่มรายการใหม่ลงในอินสแตนซ์ MemoryCache การวิเคราะห์พฤติกรรมภายในซึ่งจะขับไล่รายการเพิ่มเติมจาก MemoryCache จะค่อยๆ ... " msdn.microsoft .com / en-us / library / …
Sully

1
@ Zeus ฉันคิดว่า MSFT ลบปัญหานี้ออกไป ไม่ว่าในกรณีใด MSFT ได้ปิดปัญหาหลังจากการสนทนากับฉันโดยที่พวกเขาบอกฉันว่าขีด จำกัด จะใช้หลังจาก PoolingTime หมดลงแล้ว
Bruno Brant

คำตอบ:


100

ว้าวฉันใช้เวลามากเกินไปในการขุดรอบ CLR ด้วยตัวสะท้อนแสง แต่ในที่สุดฉันก็สามารถจัดการกับสิ่งที่เกิดขึ้นที่นี่ได้เป็นอย่างดี

กำลังอ่านการตั้งค่าอย่างถูกต้อง แต่ดูเหมือนว่าจะมีปัญหาที่ฝังลึกอยู่ในตัว CLR ซึ่งดูเหมือนว่าจะทำให้การตั้งค่าขีด จำกัด หน่วยความจำไร้ประโยชน์

รหัสต่อไปนี้จะสะท้อนออกจาก System.Runtime.Caching DLL สำหรับคลาส CacheMemoryMonitor (มีคลาสที่คล้ายกันที่ตรวจสอบหน่วยความจำฟิสิคัลและเกี่ยวข้องกับการตั้งค่าอื่น แต่นี่เป็นสิ่งที่สำคัญกว่า):

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);
}

สิ่งแรกที่คุณอาจสังเกตเห็นก็คือมันไม่ได้พยายามดูขนาดของแคชจนกว่าจะมีการรวบรวมขยะ Gen2 แต่เพียงแค่ถอยกลับไปที่ค่าขนาดที่จัดเก็บที่มีอยู่ใน cacheSizeSamples ดังนั้นคุณจะไม่สามารถเข้าถึงเป้าหมายได้เลย แต่ถ้าส่วนที่เหลือใช้งานได้อย่างน้อยเราก็จะได้รับการวัดขนาดก่อนที่เราจะประสบปัญหาจริง

ดังนั้นสมมติว่า Gen2 GC เกิดขึ้นเราพบปัญหาที่ 2 ซึ่งก็คือ ref2.ApproximateSize ทำงานที่น่ากลัวในการประมาณขนาดของแคชจริงๆ Slogging ผ่านขยะ CLR ฉันพบว่านี่คือ System.SizedReference และนี่คือสิ่งที่ทำเพื่อรับค่า (IntPtr เป็นตัวจัดการวัตถุ MemoryCache เอง):

[SecurityCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern long GetApproximateSizeOfSizedRef(IntPtr h);

ฉันคิดว่าการประกาศจากภายนอกหมายความว่าจะดำดิ่งลงสู่พื้นที่หน้าต่างที่ไม่มีการจัดการ ณ จุดนี้และฉันไม่รู้ว่าจะเริ่มค้นหาได้อย่างไรว่ามันทำอะไรที่นั่น จากสิ่งที่ฉันสังเกตเห็นแม้ว่ามันจะเป็นงานที่น่ากลัวในการพยายามประมาณขนาดของสิ่งต่างๆโดยรวม

สิ่งที่เห็นได้ชัดเจนประการที่สามคือการเรียกผู้จัดการ UpdateCacheSize ซึ่งดูเหมือนว่าควรทำอะไรบางอย่าง ขออภัยในตัวอย่างปกติของวิธีการทำงานนี้ s_memoryCacheManager จะเป็นโมฆะเสมอ ฟิลด์นี้ถูกตั้งค่าจาก ObjectCache.Host ซึ่งเป็นสมาชิกแบบคงที่สาธารณะ สิ่งนี้จะเปิดเผยให้ผู้ใช้ยุ่งด้วยหากเขาเลือกเช่นนั้นและฉันก็สามารถทำให้สิ่งนี้ทำงานได้อย่างที่ควรจะเป็นโดยการรวมการใช้งาน IMemoryCacheManager ของตัวเองเข้าด้วยกันตั้งค่าเป็น ObjectCache.Host จากนั้นเรียกใช้ตัวอย่าง . ในตอนนั้นดูเหมือนว่าคุณอาจจะใช้แคชของคุณเองและไม่ต้องกังวลกับสิ่งเหล่านี้ทั้งหมดโดยเฉพาะอย่างยิ่งเมื่อฉันไม่รู้ว่าจะตั้งค่าคลาสของคุณเองเป็น ObjectCache หรือไม่

ฉันต้องเชื่อว่าอย่างน้อยส่วนหนึ่งของสิ่งนี้ (ถ้าไม่ใช่สองส่วน) เป็นเพียงจุดบกพร่อง เป็นเรื่องดีที่ได้ทราบจากคนที่ MS ว่าข้อตกลงนี้เป็นอย่างไร

รุ่น TLDR ของคำตอบยักษ์นี้: สมมติว่า CacheMemoryLimitMegabytes ถูกจับอย่างสมบูรณ์ ณ เวลานี้ คุณสามารถตั้งค่าเป็น 10 MB จากนั้นดำเนินการต่อเพื่อเติมแคชเป็น ~ 2GB และกำจัดข้อยกเว้นหน่วยความจำออกโดยไม่มีการสะดุดของการลบรายการ


4
คำตอบที่ดีขอบคุณ ฉันล้มเลิกความพยายามที่จะคิดว่าเกิดอะไรขึ้นกับสิ่งนี้และตอนนี้จัดการขนาดแคชโดยการนับรายการเข้า / ออกและโทร. Trim () ด้วยตนเองตามต้องการ ฉันคิดว่า System.Runtime.Caching เป็นตัวเลือกที่ง่ายสำหรับแอปของฉันเนื่องจากดูเหมือนว่าจะมีการใช้กันอย่างแพร่หลายและฉันคิดว่าจะไม่มีข้อบกพร่องใด ๆ
Canacourse

3
ว้าว. นั่นเป็นเหตุผลที่ฉันรัก SO ฉันพบพฤติกรรมเดียวกันเขียนแอปทดสอบและจัดการพีซีของฉันขัดข้องหลายครั้งแม้ว่าเวลาในการสำรวจจะต่ำถึง 10 วินาทีและขีด จำกัด หน่วยความจำแคชคือ 1MB ขอบคุณสำหรับข้อมูลเชิงลึกทั้งหมด
Bruno Brant

7
ฉันรู้ว่าฉันเพิ่งพูดถึงที่นั่นในคำถาม แต่เพื่อความสมบูรณ์ฉันจะพูดถึงที่นี่อีกครั้ง ฉันได้เปิดปัญหาที่ Connect สำหรับสิ่งนี้ connect.microsoft.com/VisualStudio/feedback/details/806334/…
Bruno Brant

1
ฉันใช้ MemoryCache สำหรับข้อมูลบริการภายนอกและเมื่อฉันทดสอบโดยการฉีดขยะลงใน MemoryCache มันจะทำการตัดแต่งเนื้อหาอัตโนมัติ แต่เมื่อใช้ค่าขีด จำกัด เปอร์เซ็นต์เท่านั้น ขนาดสัมบูรณ์ไม่ได้ จำกัด ขนาดอย่างน้อยที่สุดเมื่อสอดใส่ด้วยตัวสร้างโปรไฟล์หน่วยความจำ ไม่ได้ทดสอบแบบวนซ้ำ แต่โดยการใช้งานที่ "เหมือนจริง" มากกว่า (เป็นระบบแบ็กเอนด์ดังนั้นฉันจึงเพิ่มบริการ WCF ซึ่งช่วยให้ฉันฉีดข้อมูลลงในแคชตามความต้องการ)
Svend

ปัญหานี้ยังคงเป็นปัญหาใน. NET Core หรือไม่
Павле

29

ฉันรู้ว่าคำตอบนี้มันบ้าไปแล้ว แต่ก็ดีกว่าไม่สาย ฉันอยากจะแจ้งให้คุณทราบว่าฉันได้เขียนเวอร์ชันMemoryCacheที่แก้ไขปัญหา Gen 2 Collection ให้คุณโดยอัตโนมัติ ดังนั้นจึงจดจ้องเมื่อใดก็ตามที่ช่วงการสำรวจบ่งชี้ถึงความกดดันของหน่วยความจำ หากคุณกำลังประสบปัญหานี้ให้ไปเลย!

http://www.nuget.org/packages/SharpMemoryCache

คุณยังสามารถค้นหาได้ใน GitHub หากคุณอยากรู้ว่าฉันแก้ไขมันอย่างไร รหัสค่อนข้างง่าย

https://github.com/haneytron/sharpmemorycache


2
สิ่งนี้ใช้งานได้ตามที่ตั้งใจทดสอบด้วยเครื่องกำเนิดไฟฟ้าที่เติมแคชด้วยสตริงจำนวน 1,000 อักขระ แม้ว่าการเพิ่มสิ่งที่ควรจะเป็น 100MB ในแคชจะเพิ่มขึ้นจริง 200 - 300MB ในแคชซึ่งฉันพบว่าค่อนข้างแปลก บางทีฉันอาจจะไม่ได้นับ
Karl Cassar

5
สตริง @KarlCassar ใน. NET มี2n + 20ขนาดโดยประมาณตามไบต์nความยาวของสตริงอยู่ที่ใด ส่วนใหญ่เกิดจากการรองรับ Unicode
Haney

5

ฉันเคยพบปัญหานี้เช่นกัน ฉันกำลังแคชวัตถุที่ถูกยิงเข้าไปในกระบวนการของฉันหลายสิบครั้งต่อวินาที

ฉันได้พบการตั้งค่าและการใช้งาน Frees รายการต่อไปนี้ทุก 5 วินาทีส่วนใหญ่ของเวลา

App.config:

จดcacheMemoryLimitMegabytes เมื่อสิ่งนี้ถูกตั้งค่าเป็นศูนย์ขั้นตอนการกวาดล้างจะไม่เริ่มทำงานในเวลาที่เหมาะสม

   <system.runtime.caching>
    <memoryCache>
      <namedCaches>
        <add name="Default" cacheMemoryLimitMegabytes="20" physicalMemoryLimitPercentage="0" pollingInterval="00:00:05" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>  

การเพิ่มแคช:

MemoryCache.Default.Add(someKeyValue, objectToCache, new CacheItemPolicy { AbsoluteExpiration = DateTime.Now.AddSeconds(5), RemovedCallback = cacheItemRemoved });

การยืนยันว่าการลบแคชใช้งานได้:

void cacheItemRemoved(CacheEntryRemovedArguments arguments)
{
    System.Diagnostics.Debug.WriteLine("Item removed from cache: {0} at {1}", arguments.CacheItem.Key, DateTime.Now.ToString());
}

4

ฉันได้ทำการทดสอบกับตัวอย่างของ @Canacourse และการปรับเปลี่ยน @woany และฉันคิดว่ามีสายสำคัญบางอย่างที่ขัดขวางการล้างแคชหน่วยความจำ

public void CacheItemRemoved(CacheEntryRemovedArguments Args)
{
    // this WriteLine() will block the thread of
    // the MemoryCache long enough to slow it down,
    // and it will never catch up the amount of memory
    // beyond the limit
    Console.WriteLine("...");

    // ...

    // this ReadKey() will block the thread of 
    // the MemoryCache completely, till you press any key
    Console.ReadKey();
}

แต่ทำไมการปรับเปลี่ยนของ @woany จึงดูเหมือนจะทำให้หน่วยความจำอยู่ในระดับเดิม? ประการแรกไม่ได้ตั้งค่า RemovedCallback และไม่มีคอนโซลเอาต์พุตหรือรออินพุตที่อาจบล็อกเธรดของแคชหน่วยความจำ

ประการที่สอง ...

public void AddItem(string Name, string Value)
{
    // ...

    // this WriteLine will block the main thread long enough,
    // so that the thread of the MemoryCache can do its work more frequently
    Console.WriteLine("...");
}

เธรดการนอนหลับ (1) ทุก ~ 1,000 รายการเพิ่ม () จะมีผลเช่นเดียวกัน

ไม่ใช่การตรวจสอบปัญหาที่ลึกซึ้งมากนัก แต่ดูเหมือนว่าเธรดของ MemoryCache ไม่ได้รับเวลา CPU เพียงพอในการทำความสะอาดในขณะที่มีการเพิ่มองค์ประกอบใหม่ ๆ


3

ฉัน (ขอบคุณ) สะดุดกับโพสต์ที่มีประโยชน์นี้เมื่อวานตอนที่พยายามใช้ MemoryCache เป็นครั้งแรก ฉันคิดว่ามันจะเป็นกรณีง่ายๆในการตั้งค่าและใช้คลาส แต่ฉันพบปัญหาที่คล้ายคลึงกันดังที่ระบุไว้ข้างต้น เพื่อลองดูว่าเกิดอะไรขึ้นฉันดึงซอร์สโดยใช้ ILSpy จากนั้นตั้งค่าการทดสอบและก้าวผ่านโค้ด รหัสทดสอบของฉันคล้ายกับโค้ดด้านบนมากดังนั้นฉันจะไม่โพสต์ จากการทดสอบของฉันฉันสังเกตเห็นว่าการวัดขนาดแคชไม่เคยแม่นยำเป็นพิเศษ (ตามที่กล่าวไว้ข้างต้น) และเนื่องจากการใช้งานปัจจุบันจะไม่ทำงานได้อย่างน่าเชื่อถือ อย่างไรก็ตามการวัดทางกายภาพเป็นไปด้วยดีและหากวัดหน่วยความจำกายภาพในทุกการสำรวจแล้วสำหรับฉันดูเหมือนว่ารหัสจะทำงานได้อย่างน่าเชื่อถือ ดังนั้นฉันจึงลบการตรวจสอบการรวบรวมขยะ gen 2 ภายใน MemoryCacheStatistics;

ในสถานการณ์ทดสอบเห็นได้ชัดว่าสิ่งนี้สร้างความแตกต่างอย่างมากเนื่องจากแคชถูกโจมตีอย่างต่อเนื่องดังนั้นวัตถุจึงไม่มีโอกาสไปถึง gen 2 ฉันคิดว่าเราจะใช้รุ่นดัดแปลงของ dll นี้ในโครงการของเราและใช้ MS อย่างเป็นทางการ สร้างเมื่อ. net 4.5 ออกมา (ซึ่งตามบทความการเชื่อมต่อที่กล่าวถึงข้างต้นควรมีการแก้ไข) ฉันเห็นเหตุผลว่าทำไมการตรวจสอบ gen 2 จึงถูกนำมาใช้ แต่ในทางปฏิบัติฉันไม่แน่ใจว่ามันสมเหตุสมผลหรือไม่ หากหน่วยความจำถึง 90% (หรือขีด จำกัด ใด ๆ ก็ตามที่กำหนดไว้) ก็ไม่สำคัญว่าจะมีคอลเล็กชัน gen 2 เกิดขึ้นหรือไม่ก็ตามควรขับไล่รายการโดยไม่คำนึงถึง

ฉันปล่อยให้รหัสทดสอบของฉันทำงานเป็นเวลาประมาณ 15 นาทีโดยตั้งค่า PhysicalMemoryLimitPercentage เป็น 65% ฉันเห็นว่าการใช้งานหน่วยความจำยังคงอยู่ระหว่าง 65-68% ในระหว่างการทดสอบและเห็นว่ามีการขับไล่สิ่งต่างๆอย่างเหมาะสม ในการทดสอบของฉันฉันตั้งค่า pollingInterval เป็น 5 วินาที, physicalMemoryLimitPercentage ถึง 65 และ physicalMemoryLimitPercentage เป็น 0 เป็นค่าเริ่มต้น

ทำตามคำแนะนำข้างต้น; สามารถใช้ IMemoryCacheManager เพื่อขับไล่สิ่งต่างๆออกจากแคช อย่างไรก็ตามจะต้องทนทุกข์ทรมานจากปัญหาการตรวจสอบ gen 2 ที่กล่าวถึง แม้ว่านี่อาจไม่ใช่ปัญหาในรหัสการผลิตและอาจทำงานได้เพียงพอสำหรับผู้ใช้ทั้งนี้ขึ้นอยู่กับสถานการณ์


4
การอัปเดต: ฉันใช้. NET framework 4.5 และไม่สามารถแก้ไขปัญหาได้ แคชสามารถขยายใหญ่พอที่จะทำให้เครื่องพังได้
Bruno Brant

คำถาม: คุณมีลิงก์ไปยังบทความเชื่อมต่อที่คุณกล่าวถึงหรือไม่
Bruno Brant


3

ปรากฎว่ามันไม่ใช่ข้อผิดพลาดสิ่งที่คุณต้องทำคือการตั้งค่าช่วงเวลาการรวมเพื่อบังคับใช้ขีด จำกัด ดูเหมือนว่าหากคุณไม่ได้ตั้งค่าการรวมกลุ่มไว้มันจะไม่เกิดขึ้นฉันเพิ่งทดสอบและไม่จำเป็นต้องห่อ หรือรหัสพิเศษใด ๆ :

 private static readonly NameValueCollection Collection = new NameValueCollection
        {
            {"CacheMemoryLimitMegabytes", "20"},
           {"PollingInterval", TimeSpan.FromMilliseconds(60000).ToString()}, // this will check the limits each 60 seconds

        };

ตั้งค่าเป็น " PollingInterval" ตามความเร็วของแคชที่เพิ่มขึ้นหากเติบโตเร็วเกินไปให้เพิ่มความถี่ในการตรวจสอบโพลมิฉะนั้นให้ตรวจสอบไม่ถี่มากเพื่อไม่ให้เกิดค่าใช้จ่าย


1

หากคุณใช้คลาสที่แก้ไขต่อไปนี้และตรวจสอบหน่วยความจำผ่านตัวจัดการงานจะถูกตัดแต่ง:

internal class Cache
{
    private Object Statlock = new object();
    private int ItemCount;
    private long size;
    private MemoryCache MemCache;
    private CacheItemPolicy CIPOL = new CacheItemPolicy();

    public Cache(double CacheSize)
    {
        NameValueCollection CacheSettings = new NameValueCollection(3);
        CacheSettings.Add("cacheMemoryLimitMegabytes", Convert.ToString(CacheSize));
        CacheSettings.Add("pollingInterval", Convert.ToString("00:00:01"));
        MemCache = new MemoryCache("TestCache", CacheSettings);
    }

    public void AddItem(string Name, string Value)
    {
        CacheItem CI = new CacheItem(Name, Value);
        MemCache.Add(CI, CIPOL);

        Console.WriteLine(MemCache.GetCount());
    }
}

คุณกำลังบอกว่ามันทำหรือไม่ได้รับการตัดแต่ง?
Canacourse

ใช่มันจะถูกตัดแต่ง MemoryCacheแปลกพิจารณาปัญหาทุกคนที่ดูเหมือนจะมีด้วย ฉันสงสัยว่าทำไมตัวอย่างนี้ถึงใช้งานได้
Daniel Lidström

1
ฉันไม่ทำตามมัน ฉันพยายามทำซ้ำตัวอย่าง แต่แคชยังคงเติบโตไปเรื่อย ๆ
Bruno Brant

คลาสตัวอย่างที่สับสน: "Statlock", "ItemCount", "size" ไม่มีประโยชน์ ... NameValueCollection (3) เก็บได้ 2 รายการเท่านั้นหรือ ... ในความเป็นจริงคุณสร้างแคชด้วยคุณสมบัติ sizelimit และ polInterval ไม่มีอะไรมาก! ปัญหา "ไม่ขับไล่" ไม่แตะต้อง ...
ร์นฮาร์ด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.