18 votos

La desactivación de ASP.NET HttpHandler la caché de respuesta

De fondo

Estoy en el medio de la comparación del rendimiento de NancyFx y ServiceStack.NET se ejecuta en IIS 7 (prueba en un Windows 7 de host). Ambos son increíblemente rápido - pruebas localmente cada uno de los procesos del marco de más de 10.000+ req/s, con ServiceStack siendo aproximadamente un 20% más rápido.

El problema que me estoy quedando en es que ASP.NET parece ser caché las respuestas para cada una de las URI de la solicitud de la HttpHandler, rápidamente lleva a la enorme presión de memoria (3+ Apg) y el exceso de trabajo el recolector de basura (~25% del tiempo consumido por el GC). Hasta ahora he sido incapaz de deshabilitar el almacenamiento en caché y la acumulación de objetos, y estoy buscando sugerencias sobre cómo deshabilitar este comportamiento.

Detalles

La solicitud de bucle es básicamente el siguiente:

for i = 1..100000:
    string uri = http://localhost/users/{i}
    Http.Get(uri)

La respuesta es un simple objeto JSON, con el formato { id de usuario: n }.

He abierto WinDBG, y para cada solicitud hay:

  • Uno System.Web.FileChangeEventHandler
  • Dos System.Web.Configuration.MapPathCacheInfos
  • Dos System.Web.CachedPathDatas
  • Tres System.Web.Caching.CacheDependencys
  • Cinco System.Web.Caching.CacheEntrys

Obviamente, estos elementos de la caché son lo que me lleva a creer que es una caché de hinchazón problema (me encantaría deshacerse de 150.000 objetos inservibles!).

Lo que yo he probado hasta ahora

  • En IIS 'HTTP Resonse Encabezados', 'Vencen contenido de la Web' a 'de inmediato'.
  • En la web.config

    <system.web>
     <caching>
        <outputCache enableOutputCache="false" enableFragmentCache="false"/>
      </caching>
    </system.web>
    
  • También en la web.config (y muchas variaciones en las políticas, incluyendo a ninguno).

    <caching enabled="false" enableKernelCache="false">
      <profiles>
        <add policy="DontCache" kernelCachePolicy="DontCache" extension="*/>
      </profiles>
    </caching>
    
  • Miró a través del código fuente de los marcos de referencia para ver si puede haber alguna "características", construido en el que iba a usar ASP.NET el almacenamiento en caché. Mientras que hay de almacenamiento en caché de los ayudantes, que son privadas para el marco en sí, y no parece que aprovechar ASP.NET el almacenamiento en caché.

Actualización #1

Cavar a través de reflector he encontrado que el valor de UrlMetadataSlidingExpiration a cero, se elimina una gran parte del uso excesivo de la memoria, a expensas de la corte de rendimiento en un 50% (el FileAuthorizationModule clase almacena en caché el FileSecurityDescriptors, que debe ser algo caro para generar, cuando UrlMetadataSlidingExpiration no es cero).

Esto se hace mediante la actualización de la web.config y colocando el siguiente :

<hostingEnvironment urlMetadataSlidingExpiration="00:00:00"/>

Voy a probar a deshabilitar totalmente el FileAuthorizationModule de ejecución, si es posible, a ver si eso ayuda. Sin embargo, ASP.NET todavía está generando 2*N MapPathCacheInfo y CacheEntry objetos, de modo que la memoria es todavía consumidos, solo en ritmo mucho más lento.

Actualización #2

La otra mitad del problema es el mismo problema que se describe a continuación: Prevenir muchas de las diferentes MVC Url de llenado ASP.NET Caché. Configuración

<cache percentagePhysicalMemoryUsedLimit="1" privateBytesPollTime="00:00:01"/> ayuda, pero incluso con estos muy agresivo configuración de uso de memoria se eleva rápidamente a 2.5 GB (en comparación con la de 4GB). Idealmente, estos objetos nunca se creó en el primer lugar. En su defecto, puede recurrir a un hacky solución de uso de la reflexión para borrar las Cachés (todas estas entradas son "privados" y no se enumeran cuando se itera sobre el público de la Caché).

2voto

sonjz Puntos 926

Creo que esto es menos de un problema de la caché, y más de un problema de "alta utilización de la memoria".

Dos cosas,

Si utiliza un IDisposable amistoso objeto (pruebe uno que puede utilizar el "uso" de la palabra clave). Esto le permitirá disponer de los objetos más temprano que tarde, la creación de una menor presión para el recolector de basura en el largo plazo.

for (int i = 0; i < 10000; i++) {
    using (System.Net.WebClient c = new System.Net.WebClient()) {
        System.IO.Stream stream = c.OpenRead(String.Format("http://url.com/{0}", i));

    }
}

A partir de su pseudo-código, sólo puedo suponer que usted está utilizando el Sistema.Net.WebHttpRequest que no es desechable y probablemente colgar alrededor, más de lo que debería si usted está haciendo llamadas sucesivas.

En segundo lugar, si usted está haciendo llamadas sucesivas a un servidor externo, yo pondría los retrasos entre cada una de las llamadas. Esto le dará espacio para respirar como su procesador de proceso de la para-bucle mucho más rápido que la red va a tener tiempo para responder (y sólo mantendrá la cola de las solicitudes y la ralentización de la velocidad de la que en realidad está siendo procesado).

System.Threading.Thread.Sleep(250);

Obviamente, la mejor solución sería hacer una sola llamada con una lista de los usuarios que desea recuperar y tratar sólo con uno de webrequest/respuesta.

2voto

lstern Puntos 1079

Una respuesta tardía para los demás que sufre el mismo problema:

Este es un problema conocido: KB 2504047

Este problema se produce porque la única de las solicitudes que se intente acceder a los mismos recursos se almacenan en caché como MapPathCacheInfo objetos durante 10 minutos.

Mientras que los objetos se almacenan en caché por 10 minutos, el consumo de memoria de el W3wp.exe proceso aumenta considerablemente.

Usted puede descargarlo aquí

1voto

Frazell Thomas Puntos 4455

Garantizar la IsReusable propiedad se establece en false, para IIS no volver a utilizar el mismo proceso de solicitud de atender la solicitud.

http://support.microsoft.com/kb/308001

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: