asp.net - net - ¿La sesión del alcance de MemoryCache o la aplicación es amplia?
memory cache c#.net core (2)
Estoy usando MemoryCache
en ASP.NET y está funcionando bien. Tengo un objeto que se almacena en caché durante una hora para evitar nuevas extracciones de datos del repositorio.
Puedo ver que el almacenamiento en caché funciona en la depuración, pero también una vez implementado en el servidor, después de que se realiza la primera llamada y el objeto se almacena en caché, las llamadas posteriores son aproximadamente 1/5 de las veces.
Sin embargo, me doy cuenta de que cada nueva llamada de cliente (aún dentro de esa ventana de 1 hora, de hecho solo un minuto o 2 después) parece tener la 1ra llamada a mi servicio (que está haciendo el almacenamiento en caché) casi tan larga como la original llamar antes de que los datos se almacenaran en caché.
Esto me hizo comenzar a preguntarme: ¿es específica la sesión MemoryCache
, y cada nuevo cliente que realiza la llamada está almacenando su propio caché, o hay algo más que hace que la primera llamada tarde tanto tiempo incluso después de saber que los datos se almacenaron en caché?
Desde MSDN :
Las principales diferencias entre las clases Cache y MemoryCache son que la clase MemoryCache se ha modificado para que las aplicaciones .NET Framework que no son aplicaciones ASP.NET puedan usarlas. Por ejemplo, la clase MemoryCache no tiene dependencias en el ensamblado System.Web. Otra diferencia es que puede crear varias instancias de la clase MemoryCache para usar en la misma aplicación y en la misma instancia de AppDomain.
Al leer eso y al investigar un poco sobre el código reflejado, es obvio que MemoryCache
es solo una clase simple. Puede usar la propiedad MemoryCache.Default
para (re) usar la misma instancia o puede construir tantas instancias como desee (aunque se recomienda la menor cantidad posible).
Entonces, básicamente, la respuesta está en tu código.
Si usa MemoryCache.Default
, su caché MemoryCache.Default
viva mientras viva su grupo de aplicaciones. (Solo para recordarle que el tiempo de espera inactivo del grupo de aplicaciones predeterminado es de 20 minutos, que es inferior a 1 hora).
Si lo crea utilizando la new MemoryCache(string, NameValueCollection)
entonces las consideraciones mencionadas anteriormente se aplican más el contexto en el que crea su instancia, es decir, si crea su instancia dentro del controlador (que espero que no sea el caso) entonces su caché Una solicitud
Es una pena que no encuentre ninguna referencia, pero ... MemoryCache
no garantiza que se MemoryCache
datos de acuerdo con una política de caché que usted especifique. En particular, si la máquina en la que está ejecutando su aplicación se estresa en la memoria, su memoria caché podría descartarse.
Si aún no tiene suerte para averiguar cuál es el motivo de la invalidación temprana del elemento de caché, puede aprovechar RemoveCallback
e investigar cuál es el motivo de la invalidación del elemento.
Revisando esto un año después, descubrí algo más de información en mi publicación original sobre la caché "cayendo" al azar. MSDN establece lo siguiente para las propiedades de caché configurables CacheMemoryLimitMegabytes
y PhysicalMemoryLimitPercentage
:
El valor predeterminado es 0, lo que significa que la heurística de autoescala de la clase MemoryCache se usa de forma predeterminada.
Al hacer algo de descompilación e investigación, hay escenarios predeterminados en lo profundo de la clase CacheMemoryMonitor.cs
que definen los umbrales de memoria. Aquí hay una muestra de los comentarios en esa clase en la propiedad 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.
No es necesariamente que los valores específicos sean tan importantes como darse cuenta de por qué se usa a menudo el caché: para almacenar objetos grandes que no queremos recuperar una y otra vez. Si estos objetos grandes se almacenan en la memoria caché y se excede el umbral de memoria de los entornos de alojamiento en función de estos cálculos internos, es posible que se elimine automáticamente el elemento de la memoria caché. Esto ciertamente podría explicar mi OP porque estaba almacenando una gran colección en memoria en un servidor alojado con probablemente 2GB de memoria ejecutando múltiples aplicaciones en IIS.
Hay una anulación explícita para establecer estos valores. Puede a través de la configuración (o al configurar la instancia de MemoryCache
) establecer los valores CacheMemoryLimitMegabytes
y PhysicalMemoryLimitPercentage
. Aquí hay una muestra modificada del siguiente enlace de MSDN donde configuré physicalMemoryPercentage
en 95 (%):
<configuration>
<system.runtime.caching>
<memoryCache>
<namedCaches>
<add name="default"
physicalMemoryPercentage="95" />
</namedCaches>
</memoryCache>
</system.runtime.caching>
</configuration>