asp.net - asp - mvc response cache
¿Cambia la frecuencia de caducidad del elemento de caché ASP.NET? (4)
Noté que los elementos de la memoria caché de ASP.NET se inspeccionan (y posiblemente se quitan) cada 20 segundos (y curiosamente cada vez en HH: MM: 00, HH: MM: 20 y HH: MM: 40). Pasé unos 15 minutos buscando cómo cambiar este parámetro sin éxito. También intenté establecer lo siguiente en web.config, pero no ayudó:
<cache privateBytesPollTime="00:00:05" />
No estoy tratando de hacer nada loco, pero estaría bien si fuera, digamos, 5 segundos en lugar de 20, o al menos 10 para mi aplicación.
De acuerdo con la documentación , privateBytesPollTime es para "uso de memoria de proceso de trabajo" y el valor predeterminado es 1 segundo. No creo que esto se relacione con la eliminación de elementos de caché.
Confirmé tus resultados usando una devolución de llamada de eliminación de elementos: parece que los elementos se eliminan en la parte inferior del minuto, 20 y 40 segundos. Esto sugiere que un artículo puede permanecer en la memoria caché por hasta 20 segundos más allá de la configuración de AbsoluteExpiration. No pude encontrar ninguna documentación que indique si el intervalo de sondeo de 20 segundos podría cambiarse.
Hurgando con Reflector revela que el intervalo está codificado. La expiración es manejada por una clase CacheExpires
interna, cuyo constructor estático contiene
_tsPerBucket = new TimeSpan(0, 0, 20);
_tsPerBucket
es de readonly
, por lo que no puede haber ninguna configuración que lo modifique más adelante.
El temporizador que activará la comprobación de los artículos caducados se configura en CacheExpires.EnableExpirationTimer()
...
DateTime utcNow = DateTime.UtcNow;
TimeSpan span = _tsPerBucket - new TimeSpan(utcNow.Ticks % _tsPerBucket.Ticks);
this._timer = new Timer(new TimerCallback(this.TimerCallback), null,
span.Ticks / 0x2710L, _tsPerBucket.Ticks / 0x2710L);
El cálculo de span
garantiza que el temporizador se active exactamente en: 00,: 20,: 40 segundos, aunque no veo ningún motivo para molestar. El método que el temporizador llama es internal
, por lo que no creo que haya ninguna manera de configurar su propio temporizador para llamarlo más a menudo (ignorando la reflexión).
Sin embargo, la buena noticia es que no deberías tener ningún motivo para preocuparte por el intervalo. Cache.Get()
comprueba que el elemento no haya caducado y, si tiene, elimina el elemento de la memoria caché inmediatamente y devuelve un null
. Por lo tanto, nunca obtendrás un elemento caducado de la memoria caché, aunque los elementos caducados pueden permanecer en la memoria caché durante hasta 20 segundos.
Crazy, pero solución de trabajo (se necesitan todos los pasos):
// New value for cache expiration cycle
// System.Web.Caching.CacheExpires._tsPerBucket;
// Set 1 seconds instead of 20sec
const string assembly = "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
var type = Type.GetType("System.Web.Caching.CacheExpires, " + assembly, true, true);
var field = type.GetField("_tsPerBucket", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, TimeSpan.FromSeconds(1));
// Recreate cache
// HttpRuntime._theRuntime._cacheInternal = null;
// HttpRuntime._theRuntime._cachePublic = null;
type = typeof (HttpRuntime);
field = type.GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
var runtime = field.GetValue(null);
field = type.GetField("_cachePublic", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);
field = type.GetField("_cacheInternal", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);
Por lo que vale, puedes echar un vistazo a la pregunta que he hecho : he adjuntado un código de muestra que demuestra que, aunque he establecido un tiempo de expiración absoluto de 10 segundos, la devolución de llamada de actualización tiene lugar cada 40 segundos.