¿Cómo "calentar" Entity Framework? ¿Cuándo se pone "frío"?

118

No, la respuesta a mi segunda pregunta no es el invierno.

Prefacio:

He estado investigando mucho sobre Entity Framework recientemente y algo que me sigue molestando es su rendimiento cuando las consultas no están preparadas, las llamadas consultas en frío.

Revisé el artículo sobre consideraciones de rendimiento para Entity Framework 5.0. Los autores introdujeron el concepto de consultas cálidas y frías y en qué se diferencian, que yo también noté sin saber de su existencia. Aquí probablemente valga la pena mencionar que solo tengo seis meses de experiencia a mis espaldas.

Ahora sé en qué temas puedo investigar adicionalmente si quiero comprender mejor el marco en términos de rendimiento. Desafortunadamente, la mayor parte de la información en Internet está desactualizada o repleta de subjetividad, de ahí mi incapacidad para encontrar información adicional sobre el tema de las consultas Warm vs Cold .

Básicamente, lo que he notado hasta ahora es que cada vez que tengo que volver a compilar o el reciclaje llega, mis consultas iniciales se vuelven muy lentas. Cualquier lectura de datos posterior es rápida ( subjetiva ), como se esperaba.

Estaremos migrando a Windows Server 2012, IIS8 y SQL Server 2012 y, como junior, me gané la oportunidad de probarlos antes que el resto. Estoy muy feliz de que hayan presentado un módulo de preparación que preparará mi aplicación para esa primera solicitud. Sin embargo, no estoy seguro de cómo proceder con el calentamiento de mi Entity Framework.

Lo que ya sé que vale la pena hacer:

  • Genere mis Vistas de antemano como se sugiere.
  • Finalmente, mueva mis modelos a un ensamblaje separado.

Lo que considero hacer, siguiendo el sentido común, probablemente sea un enfoque incorrecto :

  • Realización de lecturas de datos ficticios en el inicio de la aplicación para calentar, generar y validar los modelos.

Preguntas:

  • ¿Cuál sería el mejor enfoque para tener alta disponibilidad en mi Entity Framework en cualquier momento?
  • ¿En qué casos Entity Framework se vuelve "frío" de nuevo? (Recompilación, reciclaje, reinicio de IIS, etc.)
Pedro
fuente
Averigüe si lo que más le afecta es la generación de vistas o la compilación de consultas. Si esta es la generación de vistas, utilice vistas precompiladas. Si estas son las consultas, ¿tiene una jerarquía muy complicada? Tenga en cuenta que las cosas caras suelen suceder una vez por dominio de aplicación y se almacenan en caché, por lo que verá este tipo de problemas cuando se descarga el dominio de aplicación y se crea uno nuevo.
Pawel
Ya mencioné la generación de vistas @Pawel, la jerarquía no es complicada, ni siquiera un poquito. Pero el problema también es principal. Siguiendo lo que dijiste, investigaré cuándo se está descargando el dominio de la aplicación. Sin embargo, eso todavía no ayuda al otro problema que está calentando Entity Framework en caso de que, como dijiste, el dominio de la aplicación se descargue. En este punto, parece que el dominio de la aplicación se está descargando más de lo que debería y no estoy seguro de por qué, el reciclaje es solo por la noche, el ralentí está configurado en 0.
Peter
4
¿Por qué cree que hacer lecturas de datos ficticios es el enfoque incorrecto?
Josh Heitzman
5
Simplemente no se siente bien, pensé que podría haber algo más elegante de lo que no soy consciente. Pero si esa es la única solución y alguien con buen conocimiento puede confirmar que no hay otra forma, simplemente lo seguiré.
Peter
1
Un problema que encontré con el grupo de aplicaciones que se cerró después de un período de tiempo sin actividad (debido al bajo tráfico) es crear un servicio que realiza una solicitud en un intervalo de tiempo establecido a una de sus páginas. Esto evita la gran demora antes de que el grupo de aplicaciones se reinicie en la primera solicitud. O puede utilizar un servicio gratuito como www.pingalive.com para hacer ping a su dominio / ip. Esto también ayuda a evitar que los objetos almacenados en caché se borren antes de que caduquen.
hatsrumandcode

Respuestas:

55
  • ¿Cuál sería el mejor enfoque para tener alta disponibilidad en mi Entity Framework en cualquier momento?

Puede optar por una combinación de vistas pregeneradas y consultas compiladas estáticas.

Static CompiledQuerys son buenas porque son rápidas y fáciles de escribir y ayudan a aumentar el rendimiento. Sin embargo, con EF5 no es necesario compilar todas sus consultas, ya que EF compilará automáticamente las consultas. El único problema es que estas consultas pueden perderse cuando se barre la caché. Por lo tanto, aún desea mantener referencias a sus propias consultas compiladas para aquellas que ocurren muy raras, pero que son costosas. Si coloca esas consultas en clases estáticas, se compilarán cuando se requieran por primera vez. Esto puede ser demasiado tarde para algunas consultas, por lo que es posible que desee forzar la compilación de estas consultas durante el inicio de la aplicación.

Pregenerar vistas es la otra posibilidad, como mencionas. Especialmente, para aquellas consultas que tardan mucho en compilarse y que no cambian. De esa manera, mueve la sobrecarga de rendimiento del tiempo de ejecución al tiempo de compilación. Además, esto no introducirá ningún retraso. Pero, por supuesto, este cambio pasa a la base de datos, por lo que no es tan fácil de manejar. El código es más flexible.

No use mucha herencia de TPT (ese es un problema de rendimiento general en EF). No cree jerarquías de herencia demasiado profundas ni demasiado amplias. Solo 2-3 propiedades específicas de alguna clase pueden no ser suficientes para requerir un tipo propio, pero podrían manejarse como propiedades opcionales (anulables) para un tipo existente.

No se aferre a un solo contexto durante mucho tiempo. Cada instancia de contexto tiene su propia caché de primer nivel que ralentiza el rendimiento a medida que crece. La creación de contexto es barata, pero la gestión del estado dentro de las entidades almacenadas en caché del contexto puede resultar costosa. Los otros cachés (plan de consulta y metadatos) se comparten entre contextos y morirán junto con el AppDomain.

En general, debe asegurarse de asignar contextos con frecuencia y usarlos solo por un corto tiempo, que pueda iniciar su aplicación rápidamente, que compile consultas que rara vez se usan y proporcione vistas pregeneradas para consultas que son críticas para el rendimiento y que se usan con frecuencia.

  • ¿En qué casos Entity Framework se vuelve "frío" de nuevo? (Recompilación, reciclaje, reinicio de IIS, etc.)

Básicamente, cada vez que pierde su AppDomain. IIS se reinicia cada 29 horas , por lo que nunca puede garantizar que tendrá sus instancias. Además, después de un tiempo sin actividad, AppDomain también se cierra. Debería intentar subir rápidamente de nuevo. Tal vez pueda realizar parte de la inicialización de forma asincrónica (pero tenga cuidado con los problemas de subprocesos múltiples). Puede usar tareas programadas que llaman a páginas ficticias en su aplicación durante momentos en los que no hay solicitudes para evitar que AppDomain muera, pero eventualmente lo hará.

También supongo que cuando cambie su archivo de configuración o cambie los ensamblajes, habrá un reinicio.

Andreas
fuente
Gracias Andre, eso era lo que necesitaba.
Peter
@Andreas En realidad, incluso con consultas compiladas estáticas, la primera ejecución es demasiado larga. ¿Hay alguna forma de calentarlos además de: Hacer lecturas de datos ficticias al inicio de la aplicación para calentar las cosas, generar y validar los modelos?
manishKungwani
@Andreas ¿Entonces Entity framework5 lo necesita o no? ¿Qué es diferente si lo usas en ef5 (me refiero a que aún es lento o un poco de masa o no es diferente?)
qakmak
"Static CompiledQuerys son buenas porque son rápidas y fáciles de escribir y ayudan a reducir el rendimiento". ¿Rendimiento reducido?
Mathemats
9

Si busca el máximo rendimiento en todas las llamadas, debe considerar su arquitectura detenidamente. Por ejemplo, podría tener sentido pre-almacenar en caché las búsquedas de uso frecuente en la RAM del servidor cuando la aplicación se carga en lugar de usar llamadas a la base de datos en cada solicitud. Esta técnica garantizará tiempos mínimos de respuesta de la aplicación para los datos de uso común. Sin embargo, debe asegurarse de tener una política de vencimiento que se comporte correctamente o siempre borrar su caché cada vez que se realicen cambios que afecten los datos almacenados en caché para evitar problemas con la concurrencia.

En general, debe esforzarse por diseñar arquitecturas distribuidas que solo requieran solicitudes de datos basadas en IO cuando la información almacenada en caché local se vuelva obsoleta o necesite ser transaccional. Cualquier solicitud de datos "por cable" normalmente tardará entre 10 y 1000 veces más en recuperarse que una recuperación local en la memoria caché. Este único hecho a menudo hace que las discusiones sobre "datos fríos versus cálidos" sean intrascendentes en comparación con el tema de los datos "locales versus remotos".

mcstar
fuente
Este es un buen punto que a menudo ignoro, mientras me publicitan sobre el rendimiento bruto del marco de la entidad. Analizaré esto más a fondo e investigaré más sobre los principios del almacenamiento en caché. Sin embargo, "frío versus cálido" en términos de EF sigue siendo algo que quiero entender mejor.
Peter
2
"Este único hecho a menudo hace que las discusiones sobre" datos fríos versus cálidos "sean intrascendentes en comparación con el tema de los datos" locales versus remotos ". Realmente no. Si no lo tiene almacenado en caché localmente (lo que no hará inicialmente), aún deberá presionar EF y sufrir el dolor de inicialización para preparar su caché. En los mismos lugares donde su caché no está inicializada, EF no estará inicializada. Por lo tanto, agregar una capa de almacenamiento en caché puede no ayudar si el único problema es el tiempo de inicialización de EF, pero agregará otra capa de complejidad ...
MikeJansen
8

Consejos generales.

  • Realice un registro riguroso, incluido lo que se accede y el tiempo de solicitud .
  • Realice solicitudes ficticias al inicializar su aplicación para iniciar solicitudes muy lentas que haya recogido en el paso anterior.
  • No se moleste en optimizar a menos que sea un problema real, comuníquese con el consumidor de la aplicación y pregunte. Siéntase cómodo teniendo un ciclo de retroalimentación continuo, aunque solo sea para descubrir qué necesita optimización .

Ahora para explicar por qué las solicitudes ficticias no son el enfoque incorrecto .

  • Menos complejidad : está calentando la aplicación de una manera que funcionará independientemente de los cambios en el marco, y no es necesario que averigüe las API / los componentes internos del marco posiblemente funky para hacerlo de la manera correcta .
  • Mayor cobertura : está calentando todas las capas de almacenamiento en caché a la vez relacionadas con la solicitud lenta.

Para explicar cuando un caché se vuelve "Frío".

Esto sucede en cualquier capa de su marco que aplique un caché, hay una buena descripción en la parte superior de la página de rendimiento .

  • Cuando alguna vez se debe validar una caché después de un cambio potencial que hace que la caché quede obsoleta, esto podría ser un tiempo de espera o más inteligente (es decir, un cambio en el elemento almacenado en caché).
  • Cuando se desaloja un elemento de caché, el algoritmo para hacerlo se describe en la sección "Algoritmo de desalojo de caché" en el artículo de rendimiento que vinculó. , pero en resumen.
    • La memoria caché LFRU (menos frecuentemente utilizada) en el recuento de visitas y la antigüedad con un límite de 800 elementos.

Las otras cosas que mencionó, específicamente la recompilación y reinicio de IIS, borran partes o todas las cachés de memoria.

udoprog
fuente
Esta es otra respuesta útil, muy apreciada.
Peter
3

Como ha dicho, use "vistas pregeneradas" que es realmente todo lo que necesita hacer.

Extraído de su enlace : "Cuando se generan vistas, también se validan. Desde el punto de vista del rendimiento, la gran mayoría del costo de generación de vistas es en realidad la validación de las vistas".

Esto significa que el golpe de rendimiento se producirá cuando construya el ensamblaje de su modelo. Su objeto de contexto se saltará la "consulta fría" y seguirá respondiendo durante el ciclo de vida del objeto de contexto, así como los contextos de nuevos objetos posteriores.

La ejecución de consultas irrelevantes no tendrá otro propósito que consumir recursos del sistema.

El atajo ...

  1. Omita todo ese trabajo adicional de vistas generadas previamente
  2. Crea tu contexto de objeto
  3. Dispara esa dulce consulta irrelevante
  4. Luego, simplemente mantenga una referencia al contexto de su objeto durante la duración de su proceso (no recomendado).
hotpie
fuente
2

No tengo experiencia en este marco. Pero en otros contextos, por ejemplo, Solr, las lecturas completamente ficticias no serán de mucha utilidad a menos que pueda almacenar en caché toda la base de datos (o índice).

Un mejor enfoque sería registrar las consultas, extraer las más comunes de los registros y usarlas para calentar. Solo asegúrese de no registrar las consultas de preparación ni eliminarlas de los registros antes de continuar.

estani
fuente