Является ли объем памяти MemoryCache широким сеансом или приложением?

Я использую MemoryCache в ASP.NET, и он работает хорошо. У меня есть объект, который кэшируется в течение часа, чтобы предотвратить новые извлечения данных из репозитория.

Я могу видеть, как кеширование работает при отладке, но также после развертывания на сервере, после того, как сделан 1-й вызов и объект кэшируется, последующие вызовы происходят примерно в 1/5 случаев.

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

Это заставило меня задуматься: MemoryCache зависит от сеанса, и каждый новый клиент, выполняющий вызов, хранит свой собственный кеш, или происходит что-то еще, из-за чего первый вызов занимает так много времени даже после знаете, что данные были кэшированы?


person atconway    schedule 21.05.2013    source источник
comment
См. Также stackoverflow.com/questions/20347280/   -  person Tony    schedule 16.04.2016


Ответы (2)


Из MSDN:

Основные различия между классами Cache и MemoryCache заключаются в том, что класс MemoryCache был изменен, чтобы сделать его пригодным для использования приложениями .NET Framework, которые не являются приложениями ASP.NET. Например, класс MemoryCache не зависит от сборки System.Web. Еще одно отличие состоит в том, что вы можете создать несколько экземпляров класса MemoryCache для использования в одном приложении и в одном экземпляре AppDomain.

Прочитав это и проведя некоторое исследование отраженного кода, очевидно, что MemoryCache - это всего лишь простой класс. Вы можете использовать свойство MemoryCache.Default, чтобы (повторно) использовать один и тот же экземпляр, или вы можете создать столько экземпляров, сколько захотите (хотя рекомендуется как можно меньше).

Итак, в основном ответ кроется в вашем коде.
Если вы используете MemoryCache.Default, ваш кеш живет до тех пор, пока живет ваш пул приложений. (Напомню, что время простоя пула приложений по умолчанию составляет 20 минут, что составляет менее 1 часа.)

Если вы создаете его с помощью new MemoryCache(string, NameValueCollection), тогда применяются вышеупомянутые соображения плюс контекст, в котором вы создаете свой экземпляр, то есть если вы создаете свой экземпляр внутри контроллера (что, я надеюсь, не так), тогда ваш кеш живет для одного запроса

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

Если вам все еще не удалось выяснить, в чем причина раннего аннулирования элемента кеша, вы можете воспользоваться _ 6_ и выясните, в чем причина признания элемента недействительным.

person Ramunas    schedule 22.05.2013
comment
Отличный исчерпывающий ответ, и спасибо за напоминание о тайм-ауте пула приложений. Событие, хотя это не учитывает поминутное объяснение, в целом оно было полезно. Я использую MemoryCache.Default и cache.AddOrGetExisting. Во время отладки логика работает отлично. И быстрые последующие запросы одного и того же клиента извлекаются из кеша, как и ожидалось. Это отличная информация для изучения моего вопроса. - person atconway; 22.05.2013
comment
Я хочу поставить вам +1, но тогда вам будет 70, и я чувствую, что это медвежья услуга. - person Lopsided; 26.07.2019

Просматривая это год спустя, я обнаружил некоторую дополнительную информацию в моем исходном посте о случайном «удалении» кеша. В MSDN указано следующее для настраиваемых свойств кеша CacheMemoryLimitMegabytes и PhysicalMemoryLimitPercentage:

Значение по умолчанию - 0, что означает, что по умолчанию используется эвристика автоматического изменения размера класса MemoryCache.

После некоторой декомпиляции и исследования в глубине класса CacheMemoryMonitor.cs есть предопределенные сценарии, которые определяют пороговые значения памяти. Вот примеры комментариев в этом классе к свойству AutoPrivateBytesLimit:

// Auto-generate the private bytes limit:
// - On 64bit, the auto value is MIN(60% physical_ram, 1 TB)
// - On x86, for 2GB, the auto value is MIN(60% physical_ram, 800 MB)
// - On x86, for 3GB, the auto value is MIN(60% physical_ram, 1800 MB)
//
// - If it's not a hosted environment (e.g. console app), the 60% in the above
//   formulas will become 100% because in un-hosted environment we don't launch
//   other processes such as compiler, etc.

Необязательно, чтобы конкретные значения важны так же, как понимание того, почему часто используется кеш: для хранения больших объектов, которые мы не хотим получать снова и снова. Если эти большие объекты хранятся в кэше и превышен порог памяти среды размещения, основанный на этих внутренних вычислениях, вы можете удалить элемент из кеша автоматически. Это, безусловно, могло объяснить мой OP, потому что я хранил очень большую коллекцию в памяти на размещенном сервере, вероятно, с 2 ГБ памяти, выполняющей несколько приложений в IIS.

Для установки этих значений существует явное переопределение. Вы можете через конфигурацию (или при настройке экземпляра MemoryCache) установить значения CacheMemoryLimitMegabytes и PhysicalMemoryLimitPercentage. Вот модифицированный образец из следующего MSDN ссылка, где я установил physicalMemoryPercentage на 95 (%):

<configuration>
  <system.runtime.caching>
    <memoryCache>
      <namedCaches>
          <add name="default" 
               physicalMemoryLimitPercentage="95" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>
</configuration>
person atconway    schedule 25.09.2014
comment
Это было очень полезно. Спасибо. - person Austin_G; 01.02.2019