Кэш памяти по умолчанию с политикой LRU - PullRequest
5 голосов
/ 11 марта 2012

Я пытаюсь реализовать кеширование в своем приложении и хочу использовать кеш памяти по умолчанию в C # (это требование можно изменить, если оно не будет работать). Моя проблема в том, что я не хочу превышать максимальный объем физической памяти, который у меня есть на машине, но, насколько я понимаю, я не могу добавить такое ограничение в кэш-память по умолчанию.

Как правило, политика:

  1. Если объект находился в кеше в течение 10 минут без запросов, он удаляется
  2. Если новый объект добавляется в кеш и максимальный объем доступной физической памяти близок к используемому, элементы удаляются на основе LRU

Мой кэш может содержать много разных объектов, и они варьируются от 10 Мб до 2-3 Гб, поэтому я не могу заставить работать функцию trim.

Есть ли какие-либо предложения по реализации кэша LRU, отслеживающего использование оперативной памяти? И, надеюсь, это можно сделать с помощью кешей в .net?

Редактировать

Я добавил простой пример, когда MemoryCache ограничен 100 МБ и 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 Ответ

4 голосов
/ 11 марта 2012

Похоже, класс System.Runtime.Caching.MemoryCache прекрасно подошел бы под эту задачу. Вы устанавливаете политику кэширования для каждого элемента, поэтому, если вы добавляете элемент с политикой кэширования SlidingExpiration с интервалом времени 10 минут, вы должны получить поведение, которое вы ищете.

Это только класс .Net v4, поэтому он не существует в более ранних версиях среды выполнения. Если вы находитесь в веб-контексте, кеш ASP.Net работает аналогично, но, вероятно, не позволит вам управлять системной информацией.

Вы можете установить ограничения на размер кэша при его создании, чтобы он не превышал определенный объем памяти:

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

Это должно предотвратить любую подкачку на диск, по крайней мере, в пределах вашего приложения. Если существует внешнее давление памяти или система чрезмерно агрессивно относится к подкачке памяти на диск, ваш кэш может все еще выгружаться, но не из-за чрезмерного использования в вашем приложении. Насколько мне известно, нет способа зарезервировать страницы памяти в C #.

...