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

本文关键字:内存 缓存 默认 LRU 策略 具有 | 更新日期: 2023-09-27 18:27:19

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

一般来说,政策是:

  1. 如果对象在缓存中已存在10分钟而没有请求,则会将其删除
  2. 如果将新对象添加到缓存中,并且可用物理内存的最大数量即将使用,则会根据LRU删除元素

我的缓存可以包含许多不同的对象,它们的范围从10mb到2-3gb,所以我无法真正让trim函数工作。

关于如何实现LRU缓存监控ram使用情况,有什么建议吗?希望可以使用.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());
    }
}

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

看起来System.Runtime.Caching.MemoryCache类非常适合这个要求。您根据每个项目设置缓存策略,因此,如果添加的项目的缓存策略为SlidingExpiration,时间跨度为10分钟,则应该会得到您要查找的行为。

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

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

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

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