Hace poco teníamos un problema con la caché en una aplicación ASP.NET 2.0 desarrollada en Krasis. En esta aplicación se hacía una caché basada en un criterio propio (VaryByCustom). En los equipos de desarrollo (XP) funcionaba estupendamente, pero al subirla al servidor (2003 Server) parecía comportarse erráticamente: a veces funcionaba y a veces no. Era como si hubiera algo que, fuera de nuestro control, se cargar a la caché...
...y de hecho algo había que hacía lo que le daba la gana... El recolector de memoria de caché de ASP.NET.
El caso es que ASP.NET no hace caché de las cosas siempre que se lo dices. Ni mucho menos. Depende de la memoria libre que haya, no sólo la del sistema sino también la asignada por el gestor de caché para el propio proceso de la aplicación actual. No hay un tamaño por defecto sino que el gestor lo calcula automáticamente en función de muchos factores (no documentados). Mediante el nodo caching de Web.config se puede controlar hasta cierto punto el comportamiento de la caché.
Uno de los ajustes que se pueden hacer es forzar a que la caché no se vacíe automáticamente por el gestor de caché cuando haya poca memoria. Para ello se mete en el web.config el siguiente nodo:
<caching>
<cache disableMemoryCollection = "true" />
</caching>
Con este ajuste conseguiremos que la caché se comporte siempre como es debido, aún a costa de disminuir el rendimiento en caso de que se deba paginar a disco la memoria, ya que ésta no se libera automáticamente.
Ni que decir tiene que nuestro servidor en ese momento estaba algo justo de memoria RAM y que este ajuste solucionó el problema mientras no se la ampliábamos (era mucho más costoso para el servidor tener que recalcular los datos que se cacheaban que forzar una mayor carga de memoria).
Con otros parámetros de este nodo de web.config se pueden hacer cosas curiosas:
· disableExpiration: con este en true se deshabilita la caducidad de la caché. Es decir, independientemente del tiempo de caducidad que le hayamos puesto a un elemento, éste se mantiene en memoria indefinidamente. Puede servir para hacer pruebas y depurar, aunque en la práctica no se me ocurre una aplicación real para el mismo.
· privateBytesLimit: la cantidad máxima de memoria utilizada para almacenar elementos en la caché. Si dejamos el valor a 0 (valor por defecto) ASP.NET usa su propio método para determinar este valor en función de diversos factores no documentados. Tipo: Int64.
· percentagePhysicalMemoryUsed: la cantidad máxima de memoria física del servidor (RAM) que se usará por la aplicación. No sólo por la caché sino también por cualqueir información en memoria física de la aplicación. Útil para evitar que nuestra aplicación consuma demasiada memoria en entornos que nos intere tener bajo control. Tipo: Int32.
· privateButesPollTime: intervalo de tiempo (es un TimeSpan) que indica la frecuencia con la que se comprueba la memoria utilizada para hacer uso de cualquiera de los parámetros anteriores.