Come “riscaldare” Entity Framework? Quando diventa “freddo”?

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

Prefazione:

Recentemente ho fatto molte ricerche su Entity Framework e qualcosa che mi infastidisce sono le sue prestazioni quando le query non sono state sottoposte a riscaldamento, le cosiddette cold query.

Ho esaminato l’ articolo sulle considerazioni sulle prestazioni per Entity Framework 5.0. Gli autori hanno introdotto il concetto di domande calde e fredde e il modo in cui differiscono, che ho notato anche io senza sapere della loro esistenza. Qui probabilmente vale la pena menzionare che ho solo sei mesi di esperienza alle mie spalle.

Ora so quali argomenti posso approfondire ulteriormente se voglio capire meglio la struttura in termini di prestazioni. Sfortunatamente la maggior parte delle informazioni su Internet è obsoleta o gonfia di soggettività, quindi 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 dato successivo letto è veloce ( soggettivo ), come previsto.

Effettueremo la migrazione a Windows Server 2012, IIS8 e SQL Server 2012 e, in qualità di Junior, mi sono effettivamente aggiudicato l’opportunità di testarli prima del resto. Sono molto felice di aver introdotto un modulo di riscaldamento che renderà la mia applicazione pronta per quella prima richiesta. Tuttavia, non sono sicuro di come procedere con il riscaldamento del mio Entity Framework.

Quello che già so vale la pena fare:

  • Generare le mie viste in anticipo come suggerito.
  • Alla fine spostare i miei modelli in un gruppo separato.

Quello che considero fare, andando con il buon senso, è probabilmente un approccio sbagliato :

  • Fare letture di dati fittizi all’avvio dell’applicazione per riscaldare le cose, 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 l’Entity Framework diventa di nuovo “fredda”? (Ricompilazione, riciclaggio, riavvio di IIS ecc.)

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

Puoi scegliere tra una serie di viste pregenerate e query compilate staticamente.

Statico 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 stesse. L’unico problema è che queste query possono andare perse quando la cache viene spazzata. Quindi vuoi comunque mantenere i riferimenti alle tue query compilate per quelle che si verificano solo raramente, ma che sono costose. Se metti tali query in classi statiche, queste verranno compilate quando sono richieste per la prima volta. Potrebbe essere troppo tardi per alcune query, quindi potresti dover forzare la compilazione di queste query durante l’avvio dell’applicazione.

Viste pregeneranti è l’altra possibilità, come lei menziona. Soprattutto, per quelle query che richiedono molto tempo per essere compilate e che non cambiano. In questo modo si sposta l’overhead delle prestazioni dal runtime al tempo di compilazione. Anche questo non introdurrà alcun ritardo. Ma ovviamente questo cambiamento passa attraverso il database, quindi non è così facile da gestire. Il codice è più flessibile.

Non utilizzare molta eredità TPT (si tratta di un problema di prestazioni generali in EF). Né build le 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 una 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 entity framework memorizzate nella cache del contesto può diventare costosa. Le altre cache (piano di query e metadati) vengono condivise tra i contesti e moriranno insieme all’AppDomain.

Tutto sumto, è necessario assicurarsi di allocare frequentemente i contesti e utilizzarli solo per un breve periodo, in modo da poter avviare rapidamente l’applicazione, compilare query utilizzate raramente e offrire visualizzazioni pregenerate per query che sono critiche per le prestazioni e spesso utilizzate.

  • In quali casi l’Entity Framework diventa di nuovo “fredda”? (Ricompilazione, riciclaggio, riavvio di IIS ecc.)

Fondamentalmente, ogni volta che perdi il tuo AppDomain. IIS esegue riavvii ogni 29 ore , quindi non puoi mai garantire che avrai le tue istanze in giro. Inoltre, dopo un po ‘di tempo senza attività, anche l’AppDomain viene chiuso. Dovresti cercare di tornare velocemente. Forse è ansible eseguire in parte l’inizializzazione in modo asincrono (ma attenzione ai problemi di multi-threading). È ansible utilizzare attività pianificate che richiamano pagine fittizie nell’applicazione durante i periodi in cui non ci sono richieste per impedire che AppDomain muoia, ma alla fine.

Suppongo anche che quando cambi il tuo file di configurazione o cambi gli assembly ci sarà un riavvio.

Se stai cercando il massimo delle prestazioni in tutte le chiamate, dovresti considerare attentamente la tua architettura. Ad esempio, potrebbe essere utile pre-memorizzare nella cache le ricerche spesso utilizzate nella RAM del server quando l’applicazione viene caricata anziché utilizzare le chiamate al database a ogni richiesta. Questa tecnica garantirà tempi minimi di risposta delle applicazioni per i dati comunemente usati. Tuttavia, devi essere sicuro di avere una buona politica di scadenza o di cancellare sempre la tua cache ogni volta che vengono apportate modifiche che influiscono sui dati memorizzati nella cache per evitare problemi di concorrenza.

In generale, è necessario sforzarsi di progettare architetture distribuite per richiedere solo richieste di dati basate su IO quando le informazioni memorizzate nella cache locale diventano obsolete o devono essere transazionali. Qualsiasi richiesta di dati “over the wire” impiegherà normalmente 10-1000 volte più a lungo di una cache locale, nel recupero della cache di memoria. Questo solo fatto spesso rende discordanti i “dati freddi contro quelli caldi” in confronto al problema dei dati “locale vs. remoto”.

Suggerimenti generali

  • Eseguire una registrazione rigorosa che includa l’accesso e il tempo richiesto .
  • Esegui richieste fittizie durante l’inizializzazione dell’applicazione per riavviare richieste di avvio molto lente recuperate dal passaggio precedente.
  • Non preoccuparti di ottimizzare a meno che non sia un problema reale, comunicare con il consumatore dell’applicazione e chiedere. Mettiti comodo avendo un ciclo di feedback continuo, se non altro per capire cosa ha bisogno di ottimizzazione .

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

  • Meno complessità : si sta riscaldando l’applicazione in un modo che funzionerà indipendentemente dalle modifiche nel framework e non è necessario capire le API / framework internamente funky per farlo nel modo giusto .
  • Copertura maggiore : stai riscaldando tutti i livelli del caching in una sola volta in relazione alla richiesta lenta.

Per spiegare quando una cache diventa “fredda”.

Questo succede a qualsiasi livello nel tuo framework che applica una cache, c’è una buona descrizione nella parte superiore della pagina delle prestazioni .

  • Quando una cache deve essere convalidata dopo una potenziale modifica che rende la cache obsoleta, questo potrebbe essere un timeout o più intelligente (ad es. Cambiare nell’elemento memorizzato nella cache).
  • Quando un elemento della cache è sgomberato, l’algoritmo per farlo è descritto nella sezione “Algoritmo di evasione della cache” nell’articolo sulle prestazioni che hai collegato , ma in breve.
    • LFRU (Minima frequentemente – usata recentemente) cache su hit count ed età con un limite di 800 voci.

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

Come hai detto, usa “viste pre-generate” che è tutto ciò che devi fare.

Estratto dal tuo link : “Quando vengono generate le viste, vengono anche convalidate. Dal punto di vista delle prestazioni, la maggior parte del costo della generazione della vista è in realtà la convalida delle visualizzazioni”

Ciò significa che l’impatto delle prestazioni avrà luogo quando si costruisce l’assemblaggio del modello. L’object di contesto salterà quindi la “query a freddo” e rimarrà reattivo per la durata del ciclo di vita dell’object contesto così come i successivi contesti di nuovi oggetti.

L’esecuzione di query irrilevanti non avrà altro scopo se non quello di consumare risorse di sistema.

La scorciatoia …

  1. Salta tutto il lavoro extra delle viste pre-generate
  2. Crea il tuo contesto oggettuale
  3. Spegni quella dolce domanda irrilevante
  4. Quindi tieni solo un riferimento al contesto dell’object per la durata del tuo processo (non consigliato).

Non ho esperienza in questo quadro. Ma in altri contesti, ad es. Solr, le letture fittizie non saranno di grande utilità a meno che non sia ansible memorizzare in cache l’intero DB (o indice).

Un approccio migliore sarebbe quello di registrare le query, estrarre i log più comuni dai log e usarli per riscaldarsi. Assicurati di non registrare le query di riscaldamento o rimuoverle dai log prima di procedere.