具有LRU策略的默认内存缓存

时间:2012-03-11 09:05:03

标签: c# caching memory-management lru

我正在尝试在我的应用程序中实现一些缓存,并且我想在C#中使用默认的内存缓存(如果它不起作用,则可以更改此要求)。我的问题是,不想超过我在机器上的最大物理内存量,但据我所知,我不能将这样的约束添加到默认内存缓存。

一般来说,政策是:

  1. 如果对象已在缓存中10分钟而没有请求则将其删除
  2. 如果将新对象添加到缓存中并且最大可用物理内存量接近使用,则基于LRU删除元素
  3. 我的缓存可以包含许多不同的对象,它们的范围从10mb到2-3gb,所以我无法真正使用trim函数。

    有没有关于如何实现监控ram使用情况的LRU缓存的建议?并且可以使用.net中的缓存来完成它。

    修改

    我添加了一个简单的示例,其中MemoryCache限制为100Mb和20%的物理内存,但这并没有改变任何东西。我的内存充满了删除缓存条目。请注意,轮询间隔更改为等待5秒。

    class Item
    {
        private List<Guid> data;
    
        public Item(int capacity)
        {
            this.data = new List<Guid>(capacity);
            for (var i = 0; i < capacity; i++)
                data.Add(Guid.NewGuid());
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var cache = new MemoryCache(
                "MyCache",
                new NameValueCollection
                {
                    { "CacheMemoryLimitMegabytes", "100" },
                    { "PhysicalMemoryLimitPercentage", "20" },
                    { "PollingInterval", "00:00:05" }
                });
    
            for (var i = 0; i < 10000; i++)
            {
                var key = String.Format("key{0}", i);
                Console.WriteLine("Add item: {0}", key);
                cache.Set(key, new Item(1000000), new CacheItemPolicy() { UpdateCallback = UpdateHandler } );
            }
    
            Console.WriteLine("\nDone");
            Console.ReadKey();
        }
    
        public static void UpdateHandler(CacheEntryUpdateArguments args)
        {
            Console.WriteLine("Remove: {0}, Reason: {1}", args.Key, args.RemovedReason.ToString());
        }
    }
    

1 个答案:

答案 0 :(得分:4)

看起来System.Runtime.Caching.MemoryCache类很适合这个账单。您可以基于每个项目设置缓存策略,因此如果您使用TimeSpan为10分钟添加具有SlidingExpiration缓存策略的项目,您应该获得您正在寻找的行为。

这只是一个.Net v4类,因此它在早期的运行时版本中不存在。如果您在Web上下文中,ASP.Net缓存的行为类似,但可能不会让您管理系统信息。

您可以在创建缓存大小时设置限制,使其不超过特定的内存占用量:

var myCache = new MemoryCache( 
    "MyCache",
    new NameValueCollection { { "PhysicalMemoryLimit", "50" }} // set max mem pct
    );

这应该可以防止任何分页到磁盘,至少在您的应用程序中。如果存在外部内存压力或者系统过于积极地将内存分页到磁盘,则您的缓存仍可能被分页,但不是由于您的应用程序中的过度使用。据我所知,没有办法在C#中保留内存页面。