Сеанс области памяти MemoryCache или приложение широко?
Я использую MemoryCache
в ASP.NET, и это работает хорошо. У меня есть объект, который кэшируется в течение часа, чтобы предотвратить новые извлечения данных из хранилища.
Я вижу, что кеширование работает в режиме отладки, но также после развертывания на сервере после первого вызова и кэширования объекта последующие вызовы происходят примерно в 1/5 времени.
Тем не менее, я замечаю, что каждый новый клиентский вызов (все еще в этом 1-часовом окне - фактически, через минуту или 2), кажется, имеет 1-й вызов в мой сервис (который выполняет кэширование), который занимает почти столько же времени, сколько и исходный. вызов до того, как данные были кэшированы.
Это заставило меня задуматься - это MemoryCache
специфический для сеанса, и каждый новый клиент, выполняющий вызов, хранит свой собственный кэш, или что-то еще заставляет 1-й вызов длиться так долго, даже после того, как я знаю, что данные были кэшированы?
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
не гарантирует хранение данных в соответствии с политикой кэширования, которую вы укажете. В частности, если машина, на которой вы запускаете ваше приложение, перегружена памятью, ваш кеш может быть удален.
Если вам все еще не повезло выяснить причину раннего аннулирования элемента кэша, вы можете воспользоваться RemoveCallback
и выяснить, что является причиной признания предмета недействительным.
Рассматривая это год спустя, я узнал еще кое-какую информацию в моем исходном посте о случайном "сбросе" кэша. MSDN заявляет следующее для настраиваемых свойств кэша CacheMemoryLimitMegabytes
а также PhysicalMemoryLimitPercentage
:
Значение по умолчанию равно 0, что означает, что эвристика autosize класса 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>