2008-11-06 12 views
12

Me di cuenta de que los elementos de caché de ASP.NET se inspeccionan (y posiblemente se eliminan) 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 traté de establecer lo siguiente en web.config, pero no sirvió de nada:¿Cambia la frecuencia de caducidad del elemento de caché ASP.NET?

<cache privateBytesPollTime="00:00:05" /> 

No estoy tratando de hacer algo loco, pero sería mejor si estuviera, por ejemplo, 5 segundos en lugar de 20, o al menos 10 para mi aplicación.

Respuesta

19

Hurgar con Reflector revela que el intervalo está codificado. Caducidad es manejado por una clase interna CacheExpires, cuyo constructor estático contiene

_tsPerBucket = new TimeSpan(0, 0, 20); 

_tsPerBucket es readonly, por lo que no puede ser cualquier valor de configuración que modifica más tarde.

El temporizador que activará la comprobación de los elementos caducados se establece entonces 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 asegura que se activa el temporizador exactamente sobre: ​​00,: 20: 40 segundos, , aunque no veo ninguna razón para molestarme. 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 artículo no ha expirado, y si tiene, entonces elimina el elemento de la memoria caché inmediatamente y devuelve 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.

2

De acuerdo con documentation, privateBytesPollTime es para "uso de memoria de procesos 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 utilizando 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.

0

Por lo que vale, puede echar un vistazo al question I have asked: He adjuntado un código de muestra que demuestra que aunque he configurado absolute expiration time de 10 segundos, la devolución de llamada de actualización tiene lugar cada 40 segundos.

2

loco, pero la solución de trabajo (son necesarios 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); 
Cuestiones relacionadas