Простой Кеш В Памяти



Добрый день Здесь нужно было сделать очень примитивный кэш, чтобы не пришлось лишний раз заходить в базу данных.

При этом данные в базе статичны, и вопрос не столько в обновлении данных, сколько в том, когда их выкинуть, чтобы не занимать память, а удобство использования конечно важно.

Сначала я хотел использовать MemoryCache, но он мне показался слишком запутанным, да ещё и без строгой типизации.

Пример реализации см.

в кат.



Выполнение
Общая идея такова: кэш должен быть удобным и прозрачным в использовании.

Меня вдохновил интерфейс класса ThreadLocal. Поэтому конструктору требуется фабричный метод для получения начальных значений, а затем они кэшируются.

Опять же, в моем случае я посчитал вполне логичным хранить данные по слабым ссылкам (WeakReference), чтобы до тех пор, пока данные нужны, кто-то ими пользуется, они будут доступны.

Далее по мере выделения новой памяти данные из кэша будут вытеснены.

Методов всего два: индексатор, который будет возвращать данные либо из источника, либо из кэша.

А также метод CleanCache для очистки словаря от мертвых ссылок и тем самым устранения утечек памяти.

В реальных условиях это не всегда необходимо.

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



Цель публикации
В принципе, мне интересно услышать мнения о моей реализации, как бы вы это сделали и есть ли ошибки.

Ну, если кому-то поможет, берите и пользуйтесь :)

Источник
   

public class WeakCache<TKey,TValue> where TValue : class { const int cacheCleanInterval = 60; private readonly Func<TKey, TValue> getter; private readonly Dictionary<TKey, WeakReference> data = new Dictionary<TKey, WeakReference>(); private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); private DateTime lastCacheClean = DateTime.MinValue; public WeakCache(Func<TKey,TValue> getter) { this.getter = getter; } public TValue this[TKey key] { get { CleanCache(); try { rwLock.EnterUpgradeableReadLock(); WeakReference wr; TValue val; if (data.TryGetValue(key, out wr)) { val = (TValue)wr.Target; if (val != null) return val; } try { rwLock.EnterWriteLock(); if (data.TryGetValue(key, out wr)) { val = (TValue)wr.Target; if (val != null) return val; } data[key] = new WeakReference(val = getter(key)); return val; } finally { rwLock.ExitWriteLock(); } } finally { rwLock.ExitUpgradeableReadLock(); } } } void CleanCache() { if ((DateTime.Now - lastCacheClean).

TotalSeconds > cacheCleanInterval) { try { rwLock.EnterWriteLock(); if ((DateTime.Now - lastCacheClean).

TotalSeconds > cacheCleanInterval) { lastCacheClean = DateTime.Now; var refs = data.ToArray(); foreach (var weakReference in refs) { if (!weakReference.Value.IsAlive) data.Remove(weakReference.Key); } } } finally { rwLock.ExitWriteLock(); } } } }

Теги: #C++ #кэш #.

NET #C++

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.