Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

От MSDN:

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

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

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

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

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

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

Ответ 2

Рассмотрев это через год, я узнал еще немного информации о моем исходном сообщении о том, что кеш "отбрасывается" случайным образом. MSDN заявляет следующее для настраиваемых свойств кэша CacheMemoryLimitMegabytes и PhysicalMemoryLimitPercentage:

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

Выполняя некоторую декомпиляцию и исследование, в классе 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 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" 
               physicalMemoryPercentage="95" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>
</configuration>