2011-02-18 21 views
16

Tengo una aplicación creada en ASP.NET MVC 3 que usa SQL CE para almacenamiento y EF CTP 5 para acceso a datos.ASP.NET MVC y EF Code First Memory Usage

Implementé este sitio en un host compartido solo para descubrir que se recicla constantemente ya que está llegando al límite de 100mb que establecieron en sus grupos de aplicaciones (dedicadas).

El sitio, cuando se ejecuta en modo de lanzamiento utiliza alrededor de 110mb de RAM.

He intentado utilizar SQL Server Express en lugar de CE, y esto ha supuesto una pequeña diferencia.

La única diferencia significativa es cuando eliminé EF por completo (utilizando un repositorio falso). Esto redujo el uso de memoria entre 30mb-40mb. Una plantilla MVC en blanco usa alrededor de 20mb así que pensé que esto no es tan malo.

¿Hay puntos de referencia para las aplicaciones "estándar" ASP.NET MVC?

Sería bueno saber qué utilización de memoria están recibiendo otros usuarios de EF CTP, así como algunas sugerencias para las herramientas de creación de perfiles de memoria (preferiblemente las gratuitas).

Vale la pena mencionar cómo manejo la vida del EF ObjectContext. Estoy utilizando la sesión por solicitud y crear instancias de la ObjectContext usando StructureMap:

For<IDbContext>().HttpContextScoped().Use(ctx => new MyContext("MyConnStringName")); 

Muchas gracias Ben

+1

IMO, 100MB para su grupo de aplicaciones es miserable. –

+0

Eso es lo que pensé, pero hasta que tenga algo para compararlo no tengo un caso para volver al host. –

+0

depende de cuánto pagas. Obviamente, una empresa de alojamiento compartido de $ 10/mes no va a asignar muchos más recursos para una cuenta de esa economía. Por otro lado, si pagas alrededor de $ 50/mes, deberías obtener del orden de 1GB de ram, que sería suficiente. –

Respuesta

25

Nos las arreglamos para reducir nuestra huella de memoria de manera significativa. El proceso de trabajo de IIS ahora se encuentra alrededor de 50mb en comparación con los 100 mb anteriores.

A continuación se presentan algunas de las cosas que nos ayudaron:

  • Comprobar los conceptos básicos. Asegúrese de compilar en modo de lanzamiento y establecer la depuración de compilación en falso en web.config. Es fácil olvidar tales cosas.
  • Utilice los símbolos DEBUG para el código de diagnóstico. Un ejemplo de esto sería cuando se usan herramientas como NHProf (sí, ya me atrapó esto antes). Lo más fácil es ajustar dicho código en una directiva #if DEBUG para garantizar que no se compile en el lanzamiento de su aplicación.
  • No se olvide de SQL. Los ORM hacen que sea muy fácil ignorar cómo su aplicación está hablando con su base de datos. Utilizar el Analizador de SQL o herramientas como EFProf/NHProf puede mostrarle exactamente lo que está sucediendo. En el caso de EF, probablemente te sientas un poco mal después, especialmente si haces un uso significativo de la carga diferida. Una vez que haya superado esto, puede comenzar a optimizar (vea el punto a continuación).
  • La carga diferida es conveniente pero no debe utilizarse en vistas MVC (IMO). Esta fue una de las causas principales de nuestro uso de memoria alta. La página de inicio de nuestro sitio web creaba 59 consultas individuales debido a la carga diferida (SELECCIONE N + 1).Después de crear un modelo de vista específico para esta página y cargar ansiosamente las asociaciones que necesitábamos, llegamos a 6 consultas que se ejecutaron en la mitad del tiempo.
  • Los patrones de diseño están ahí para guiarlo, no para regular el desarrollo de su aplicación. Tiendo a seguir un enfoque DDD siempre que sea posible. En este caso, realmente no quería mostrar claves externas en mi modelo de dominio. Sin embargo, dado que EF no maneja las asociaciones de muchos a uno tanto como NH (emitirá otra consulta solo para obtener la clave externa de un objeto que ya tenemos en la memoria), terminé con una consulta adicional (por objeto) mostrado en mi página. En este caso, decidí que podía soportar un poco de olor a código (incluido el FK en mi modelo) por el bien de un mejor rendimiento.
  • Una "solución" común es arrojar el almacenamiento en caché a problemas de rendimiento. Es importante identificar el problema real antes de formular su estrategia de almacenamiento en caché. Podría haber aplicado el caché de resultados a nuestra página de inicio (ver nota a continuación), pero esto no cambia el hecho de que tengo 59 consultas que llegan a mi base de datos cuando caduca.

Una nota sobre la memoria caché de salida: Cuando ASP.NET MVC fue lanzado por primera vez hemos sido capaces de hacer caché de rosquilla, es decir, el almacenamiento en caché de una página aparte de una región específica (s). El hecho de que esto ya no sea posible hace que el almacenamiento en caché de resultados sea bastante inútil si tiene información específica del usuario en la página. Por ejemplo, tenemos un estado de inicio de sesión dentro del menú de navegación del sitio. Esto solo significa que no puedo usar el almacenamiento en caché de resultados para la página, ya que también almacenaría en caché el estado de inicio de sesión.

En última instancia, no existe una regla rígida sobre cómo optimizar una aplicación. La mayor mejora en el rendimiento de nuestra aplicación se produjo cuando dejamos de usar el ORM para crear nuestras asociaciones (para la parte pública de nuestro sitio) y, en su lugar, las cargamos manualmente en nuestros viewmodels. No pudimos usar EF para cargarlos ansiosamente, ya que había demasiadas asociaciones (lo que resulta en una consulta desordenada de UNIÓN).

Un ejemplo fue nuestro mecanismo de etiquetado. Se pueden etiquetar entidades como BlogPost y Project. Las etiquetas y las entidades tagable tienen una relación muchos a muchos. En nuestro caso, era mejor recuperar todas las etiquetas y almacenarlas en caché. Luego creamos una proyección de linq para almacenar en caché las claves de asociación para nuestras entidades de tagable (por ejemplo, ProjectId/TagId). Al crear el modelo de vista para nuestra página, podríamos construir las etiquetas para cada entidad tagable sin tocar la base de datos. Una vez más, esto fue específico para nuestra aplicación, pero produjo una mejora masiva en el rendimiento y en la reducción de nuestro uso de memoria.

Algunos de los recursos/herramientas que usamos en el camino:

Si bien hicimos mejoras que nos llevarían a los límites del grupo de aplicaciones (Arvixe) de la empresa de alojamiento, siento que tengo el deber de aconsejar a las personas que están viendo sus planes para distribuidores de Windows que dichas restricciones están vigentes. (dado que Arvixe no menciona esto en ningún lugar cuando anuncia el plan). Entonces, cuando algo parece demasiado bueno para ser cierto (ilimitado x, y, z), generalmente lo es.

+0

¡Estos son consejos geniales para cualquier desarrollador de mvc! –

+0

Genial y bien documentado. Supongo que todos venimos de este problema con Arvixe, solo podemos aconsejar a otros que lo comprueben antes de firmar con Arvixe, sí, prometen x y z ilimitados ... sin palabras. – Nestor

0

Lo curioso es que creo que obtuvieron su estimación a partir de la siguiente URL:

http://blog.whitesites.com/w3wp-exe-using-too-much-memory-and-resources__633900106668026886_blog.htm

PD Es un gran artículo comprobar y ver si estás haciendo algo que el tipo está describiendo. (Por ejemplo, el almacenamiento en caché de sus páginas)

P.S.S. Acabo de verificar nuestro sistema y está funcionando a 50 megas actualmente. Estamos utilizando MVC 2 y EF CTP 4.

+0

Es bastante probable. Artículo útil de todos modos. –

Cuestiones relacionadas