Как иметь дело с дорогостоящим операционным использованием здания MemoryCache?

На проекте MVC ASP.NET у нас есть несколько экземпляров данных, которые требуют, чтобы хорошая сумма ресурсов и время создала. Мы хотим кэшировать их.

MemoryCache обеспечивает определенный уровень потокобезопасности, но недостаточно постараться не выполнять несколько экземпляров строительных норм и правил параллельно. Вот пример:

var data = cache["key"];
if(data == null)
{
  data = buildDataUsingGoodAmountOfResources();
  cache["key"] = data;
}

Как Вы видите на занятом веб-сайте, в который сотни потоков могли войти, если оператор одновременно до данных создается, и сделайте операцию здания еще медленнее, излишне использовав ресурсы сервера.

Существует атомарное AddOrGetExisting реализация в MemoryCache, но это неправильно требует, "чтобы значение установило" вместо "кода для получения значения для установки", который я думаю, представляет данный почти абсолютно бесполезный метод.

Мы использовали наши собственные специальные леса вокруг MemoryCache для разбираний в нем однако, это требует явный locks. Это является громоздким для использования объектов блокирования на запись, и мы обычно уходим путем совместного использования объектов блокирования, который далек от идеала. Это заставило меня думать, что причины избежать такой конвенции могли быть намеренными.

Таким образом, у меня есть два вопроса:

  • Действительно ли это - лучшая практика не к lock строительные нормы и правила? (Который, возможно, был доказан более быстро реагирующим для одного, интересно),

  • Что правильный путь состоит в том, чтобы достигнуть блокировки на запись для MemoryCache для такой блокировки? Сильное желание использовать key представьте в виде строки, поскольку объект блокирования отклонен в ".NET, блокирующей 101".

58
задан 18 February 2016 в 23:43

1 ответ

Решение Sedat объединения Ленивого с AddOrGetExisting является вдохновляющим. Я должен указать, что это решение имеет проблему производительности, которая кажется очень важной для решения для кэширования.

, Если Вы смотрите код из AddOrGetExisting (), Вы найдете, что AddOrGetExisting () не является свободным от блокировок методом. По сравнению со свободным от блокировок Получают () метод, он тратит впустую тот преимущества MemoryCache.

я хотел бы рекомендовать следовать за решением, использование Получают () сначала и затем используют AddOrGetExisting (), чтобы не создавать объект многократно.

public T GetFromCache<T>(string key, Func<T> valueFactory) 
{
    T value = (T)cache.Get(key);
    if (value != null)
    {
        return value;
    }

    var newValue = new Lazy<T>(valueFactory);
    // the line belows returns existing item or adds the new value if it doesn't exist
    var oldValue = (Lazy<T>)cache.AddOrGetExisting(key, newValue, MemoryCache.InfiniteExpiration);
    return (oldValue ?? newValue).Value; // Lazy<T> handles the locking itself
}
1
ответ дан 1 November 2019 в 14:44

Другие вопросы по тегам:

Похожие вопросы: