Come "riscaldare" Entity Framework? Quando fa "freddo"?


118

No, la risposta alla mia seconda domanda non è l'inverno.

Prefazione:

Recentemente ho fatto molte ricerche su Entity Framework e qualcosa che continua a darmi fastidio sono le sue prestazioni quando le query non sono riscaldate, le cosiddette query fredde.

Ho esaminato l' articolo sulle considerazioni sulle prestazioni per Entity Framework 5.0. Gli autori hanno introdotto il concetto di query Warm e Cold e come differiscono, cosa che ho notato anche io senza sapere della loro esistenza. Probabilmente vale la pena menzionare che ho solo sei mesi di esperienza alle spalle.

Ora so su quali argomenti posso ricercare ulteriormente se voglio comprendere meglio il framework in termini di prestazioni. Sfortunatamente la maggior parte delle informazioni su Internet sono obsolete o gonfie di soggettività, da qui la mia incapacità di trovare ulteriori informazioni sull'argomento delle query Warm vs Cold .

Fondamentalmente quello che ho notato finora è che ogni volta che devo ricompilare o gli hit di riciclaggio, le mie domande iniziali stanno diventando molto lente. Qualsiasi lettura successiva dei dati è veloce ( soggettiva ), come previsto.

Migreremo a Windows Server 2012, IIS8 e SQL Server 2012 e come Junior mi sono effettivamente guadagnato l'opportunità di testarli prima degli altri. Sono molto felice che abbiano introdotto un modulo di riscaldamento che preparerà la mia applicazione per quella prima richiesta. Tuttavia, non sono sicuro di come procedere con il riscaldamento di Entity Framework.

Quello che già so vale la pena fare:

  • Genera le mie visualizzazioni in anticipo come suggerito.
  • Alla fine sposta i miei modelli in un assieme separato.

Quello che considero di fare, seguendo il buon senso, probabilmente un approccio sbagliato :

  • Esecuzione di letture di dati fittizi all'avvio dell'applicazione per riscaldare, generare e convalidare i modelli.

Domande:

  • Quale sarebbe l'approccio migliore per avere un'elevata disponibilità sul mio Entity Framework in qualsiasi momento?
  • In quali casi Entity Framework si "raffredda" di nuovo? (Ricompilazione, riciclaggio, riavvio IIS ecc.)

Scopri se questa è la generazione di visualizzazioni o la compilazione di query che ti colpisce di più. Se si tratta di view gen, utilizzare le viste precompilate. Se questa è la domanda, hai una gerarchia grande e complicata? Tieni presente che le cose costose di solito si verificano una volta per dominio dell'app e vengono memorizzate nella cache, quindi vedi questo tipo di problemi quando il dominio dell'app viene scaricato e ne viene creato uno nuovo.
Pawel

Ho già menzionato la generazione della vista @Pawel, la gerarchia non è complicata, nemmeno un po '. Ma anche il problema è principale. Seguendo quanto hai detto, cercherò di verificare quando il dominio dell'app viene scaricato. Tuttavia, ciò non aiuta ancora l'altro problema che sta riscaldando Entity Framework nel caso in cui, come hai detto, il dominio dell'app venga scaricato. A questo punto, sembra che il dominio dell'app venga scaricato più del dovuto e non sono sicuro del perché, il riciclaggio è solo di notte, il minimo è impostato a 0.
Peter

4
Perché pensi che eseguire letture di dati fittizi sia l'approccio sbagliato?
Josh Heitzman

5
Semplicemente non mi sembra giusto, ho pensato che potesse esserci qualcosa di più elegante di cui non sono a conoscenza. Ma se questa è l'unica soluzione e qualcuno con una buona conoscenza può confermare che non c'è un altro modo, lo seguirò.
Peter

1
Un problema che ho riscontrato con la chiusura del pool di app dopo un periodo di inattività (a causa del traffico ridotto) è la creazione di un servizio che effettui una richiesta a un intervallo di tempo prestabilito a una delle tue pagine. Ciò impedisce il lungo ritardo prima che il pool di app venga riavviato alla prima richiesta. Oppure puoi utilizzare un servizio gratuito come www.pingalive.com per eseguire il ping del tuo dominio / IP. Questo aiuta anche a impedire che gli oggetti memorizzati nella cache vengano cancellati prima che siano scaduti.
hatsrumandcode

Risposte:


55
  • Quale sarebbe l'approccio migliore per avere un'elevata disponibilità sul mio Entity Framework in qualsiasi momento?

Puoi scegliere un mix di visualizzazioni pregenerate e query compilate statiche.

Static CompiledQuerys sono buoni perché sono veloci e facili da scrivere e aiutano ad aumentare le prestazioni. Tuttavia con EF5 non è necessario compilare tutte le query poiché EF compilerà automaticamente le query da solo. L'unico problema è che queste query possono andare perse quando la cache viene spazzata via. Quindi vuoi ancora conservare i riferimenti alle tue query compilate per quelle che si verificano solo molto rare, ma che sono costose. Se metti queste query in classi statiche, verranno compilate quando saranno richieste per la prima volta. Potrebbe essere troppo tardi per alcune query, quindi potresti voler forzare la compilazione di queste query durante l'avvio dell'applicazione.

Pregenerare le visualizzazioni è l'altra possibilità che hai menzionato. Soprattutto per quelle query che richiedono molto tempo per la compilazione e che non cambiano. In questo modo sposti l'overhead delle prestazioni dal runtime al tempo di compilazione. Anche questo non introdurrà alcun ritardo. Ma ovviamente questa modifica passa al database, quindi non è così facile da gestire. Il codice è più flessibile.

Non usare molta ereditarietà TPT (questo è un problema di prestazioni generali in EF). Non costruire gerarchie ereditarie troppo profonde né troppo ampie. Solo 2-3 proprietà specifiche per alcune classi potrebbero non essere sufficienti per richiedere un proprio tipo, ma potrebbero essere gestite come proprietà facoltative (nullable) per un tipo esistente.

Non aggrapparti a un singolo contesto per molto tempo. Ogni istanza di contesto ha la propria cache di primo livello che rallenta le prestazioni man mano che aumenta. La creazione del contesto è economica, ma la gestione dello stato all'interno delle entità cache del contesto può diventare costosa. Le altre cache (piano di query e metadati) sono condivise tra contesti e moriranno insieme all'AppDomain.

Tutto sommato dovresti assicurarti di allocare frequentemente i contesti e usarli solo per un breve periodo, di poter avviare rapidamente la tua applicazione, di compilare query che vengono utilizzate raramente e di fornire viste pregenerate per query che sono critiche per le prestazioni e spesso utilizzate.

  • In quali casi Entity Framework si "raffredda" di nuovo? (Ricompilazione, riciclaggio, riavvio IIS ecc.)

Fondamentalmente, ogni volta che perdi il tuo AppDomain. IIS esegue i riavvii ogni 29 ore , quindi non puoi mai garantire di avere le tue istanze in giro. Inoltre, dopo un po 'di tempo senza attività, anche l'AppDomain viene chiuso. Dovresti provare a risalire velocemente. Forse puoi eseguire alcune delle inizializzazioni in modo asincrono (ma fai attenzione ai problemi di multi-threading). È possibile utilizzare attività pianificate che richiamano pagine fittizie nell'applicazione durante i periodi in cui non sono presenti richieste per impedire la morte di AppDomain, ma alla fine lo farà.

Presumo anche che quando modifichi il tuo file di configurazione o modifichi gli assembly, ci sarà un riavvio.


Grazie Andre, era quello di cui avevo bisogno.
Peter

@Andreas In realtà, anche con le query compilate statiche, la prima esecuzione è troppo lunga. C'è un modo per riscaldare quelli oltre a: Eseguire letture di dati fittizi all'avvio dell'applicazione per riscaldare le cose, generare e convalidare i modelli.
manishKungwani

@Andreas So Entity framework5 ne hai bisogno o no? cosa c'è di diverso se lo uso su ef5 (intendo ancora lento o poca pastella o non diverso?)
qakmak

"Static CompiledQuerys sono buoni perché sono veloci e facili da scrivere e aiutano a ridurre le prestazioni." Prestazioni ridotte?
Mathemats

9

Se stai cercando le massime prestazioni in tutte le chiamate, dovresti considerare attentamente la tua architettura. Ad esempio, potrebbe avere senso pre-memorizzare nella cache le ricerche utilizzate spesso nella RAM del server quando l'applicazione viene caricata invece di utilizzare le chiamate al database su ogni richiesta. Questa tecnica garantirà tempi di risposta minimi dell'applicazione per i dati di uso comune. Tuttavia, è necessario assicurarsi di disporre di una politica di scadenza corretta o svuotare sempre la cache ogni volta che vengono apportate modifiche che influiscono sui dati memorizzati nella cache per evitare problemi di concorrenza.

In generale, dovresti sforzarti di progettare architetture distribuite per richiedere solo richieste di dati basate su I / O quando le informazioni memorizzate nella cache locale diventano obsolete o devono essere transazionali. Qualsiasi richiesta di dati "over the wire" richiederà normalmente 10-1000 volte più tempo per il recupero rispetto a un recupero locale nella cache di memoria. Questo fatto da solo spesso rende le discussioni sui "dati freddi e caldi" irrilevanti rispetto alla questione dei dati "locali e remoti".


Questo è un buon punto che spesso ignoro, mentre mi entusiasma per le prestazioni grezze del framework dell'entità. Approfondirò questo aspetto e cercherò di più sui principi del caching. Tuttavia, "freddo contro caldo" in termini di EF è ancora qualcosa che voglio capire meglio.
Peter

2
"Questo fatto da solo spesso rende le discussioni sui" dati freddi e caldi "irrilevanti rispetto al problema dei dati" locali e remoti "". Non proprio. Se non lo hai memorizzato nella cache locale (cosa che inizialmente non farai), dovrai comunque premere EF e subire il dolore di inizializzazione per caricare la cache. Negli stessi luoghi in cui la cache non è stata inizializzata, EF non verrà inizializzato. Quindi l'aggiunta di un livello di memorizzazione nella cache potrebbe non essere d'aiuto se l'unico problema è il tempo di inizializzazione EF, ma aggiungerà un altro livello di complessità ...
MikeJansen

8

Suggerimenti generali.

  • Eseguire la registrazione rigorosa, inclusi si accede e l' ora della richiesta .
  • Esegui richieste fittizie durante l'inizializzazione dell'applicazione per avviare a caldo le richieste molto lente che prendi dal passaggio precedente.
  • Non preoccuparti di ottimizzare a meno che non si tratti di un problema reale, comunica con il consumatore dell'applicazione e chiedi. Mettiti comodo con un ciclo di feedback continuo se non altro per capire cosa necessita di ottimizzazione .

Ora per spiegare perché le richieste fittizie non sono l'approccio sbagliato .

  • Meno complessità : stai riscaldando l'applicazione in un modo che funzionerà indipendentemente dai cambiamenti nel framework e non hai bisogno di capire le API / gli interni del framework possibilmente funky per farlo nel modo giusto .
  • Maggiore copertura : stai riscaldando tutti i livelli di memorizzazione nella cache contemporaneamente relativi alla richiesta lenta.

Per spiegare quando una cache diventa "fredda".

Ciò accade a qualsiasi livello del framework che applica una cache, c'è una buona descrizione nella parte superiore della pagina delle prestazioni .

  • Ogni volta che una cache deve essere convalidata dopo una potenziale modifica che rende la cache stantia, questo potrebbe essere un timeout o più intelligente (cioè una modifica nell'elemento memorizzato nella cache).
  • Quando un elemento della cache viene rimosso, l'algoritmo per farlo è descritto nella sezione "Algoritmo di eliminazione della cache" nell'articolo sulle prestazioni che hai collegato , ma in breve.
    • Cache LFRU (meno frequentemente - usata di recente) per numero di visite ed età con un limite di 800 elementi.

Le altre cose che hai menzionato, in particolare la ricompilazione e il riavvio di IIS, cancellano parti o tutte le cache in memoria.


Questa è un'altra risposta utile, molto apprezzata.
Peter il

3

Come hai affermato, usa "visualizzazioni pre-generate" che è davvero tutto ciò che devi fare.

Estratto dal tuo link : "Quando le visualizzazioni vengono generate, vengono anche convalidate. Dal punto di vista delle prestazioni, la stragrande maggioranza del costo di generazione delle visualizzazioni è in realtà la convalida delle visualizzazioni"

Ciò significa che il colpo di prestazione avrà luogo quando si costruisce l'assieme del modello. L'oggetto contesto salterà quindi la "query a freddo" e rimarrà reattivo per la durata del ciclo di vita dell'oggetto contesto, nonché per i successivi nuovi contesti oggetto.

L'esecuzione di query irrilevanti non avrà altro scopo che consumare risorse di sistema.

La scorciatoia ...

  1. Salta tutto il lavoro extra delle visualizzazioni pre-generate
  2. Crea il contesto dell'oggetto
  3. Spara quella dolce domanda irrilevante
  4. Quindi mantieni un riferimento al contesto dell'oggetto per la durata del processo (non consigliato).


2

Non ho esperienza in questo quadro. Ma in altri contesti, ad esempio Solr, letture completamente fittizie non saranno di grande utilità a meno che non si possa memorizzare nella cache l'intero DB (o indice).

Un approccio migliore sarebbe quello di registrare le query, estrarre quelle più comuni dai log e usarle per il riscaldamento. Assicurati solo di non registrare le query di riscaldamento o di rimuoverle dai registri prima di procedere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.