Como “aquecer” o Entity Framework? Quando fica “frio”?

118

Não, a resposta à minha segunda pergunta não é o inverno.

Prefácio:

Tenho feito muitas pesquisas sobre o Entity Framework recentemente e algo que continua me incomodando é o seu desempenho quando as consultas não são aquecidas, as chamadas consultas frias.

Eu li o artigo de considerações de desempenho para o Entity Framework 5.0. Os autores introduziram o conceito de consultas quentes e frias e como elas diferem, que eu também percebi sem saber de sua existência. Aqui provavelmente vale a pena mencionar que só tenho seis meses de experiência nas minhas costas.

Agora eu sei quais tópicos posso pesquisar adicionalmente, se quiser entender melhor a estrutura em termos de desempenho. Infelizmente, a maioria das informações na Internet está desatualizada ou inchada de subjetividade, daí minha incapacidade de encontrar qualquer informação adicional sobre o tópico de consultas Quentes vs Frias .

Basicamente, o que notei até agora é que sempre que tenho que recompilar ou os resultados de reciclagem, minhas consultas iniciais estão ficando muito lentas. Qualquer leitura de dados subsequente é rápida ( subjetiva ), conforme esperado.

Estaremos migrando para o Windows Server 2012, IIS8 e SQL Server 2012 e, como um Junior, realmente ganhei a oportunidade de testá-los antes do resto. Estou muito feliz por eles introduzirem um módulo de aquecimento que deixará meu aplicativo pronto para a primeira solicitação. No entanto, não tenho certeza de como proceder com o aquecimento do meu Entity Framework.

O que já sei vale a pena fazer:

  • Gere minhas visualizações com antecedência, conforme sugerido.
  • Por fim, mova meus modelos para uma montagem separada.

O que considero fazer, seguindo o bom senso, provavelmente é uma abordagem errada :

  • Fazer leituras de dados fictícios no início do aplicativo para aquecer, gerar e validar os modelos.

Questões:

  • Qual seria a melhor abordagem para ter alta disponibilidade em meu Entity Framework a qualquer momento?
  • Em quais casos o Entity Framework fica "frio" novamente? (Recompilação, Reciclagem, Reinício IIS etc.)
Peter
fonte
Descubra se esta é a geração de visualização ou compilação de consulta que mais atinge você. Se este for o modo de exibição, use as visualizações pré-compiladas. Se esta for a consulta - você tem uma hierarquia grande e complicada? Observe que coisas caras geralmente acontecem uma vez por domínio do aplicativo e são armazenados em cache, portanto, você vê esse tipo de problema quando o domínio do aplicativo é descarregado e um novo é criado.
Pawel
Já mencionei a geração de view @Pawel, a hierarquia não é complicada, nem um pouco. Mas o problema também é o principal. Seguindo o que você disse, pesquisarei quando o domínio do aplicativo está sendo descarregado. No entanto, isso ainda não ajuda o outro problema que está aquecendo o Entity Framework caso, como você disse, o domínio do aplicativo seja descarregado. Neste ponto, parece que o domínio do aplicativo está sendo descarregado mais do que deveria e não tenho certeza do motivo, a reciclagem ocorre apenas à noite, a ociosidade é definida como 0.
Peter
4
Por que você acha que fazer leituras de dados fictícios é a abordagem errada?
Josh Heitzman
5
Simplesmente não parece certo, pensei que poderia haver algo mais elegante que eu não sabia. Mas se essa for a única solução e alguém com bom conhecimento puder confirmar que não há outro caminho, eu simplesmente continuarei.
Peter
1
Um problema que encontrei com o encerramento do pool de aplicativos após um período de inatividade (devido ao baixo tráfego) é criar um serviço que faz uma solicitação em um intervalo de tempo definido para uma de suas páginas. Isso evita o longo atraso antes que o pool de aplicativos seja reiniciado na primeira solicitação. Ou você pode usar um serviço gratuito como www.pingalive.com para executar ping em seu domínio / ip. Isso também ajuda a evitar que seus objetos em cache sejam limpos antes de expirarem.
hatchrumandcode

Respostas:

55
  • Qual seria a melhor abordagem para ter alta disponibilidade em meu Entity Framework a qualquer momento?

Você pode escolher uma mistura de visualizações pré-geradas e consultas compiladas estáticas.

Static CompiledQuerys são bons porque são rápidos e fáceis de escrever e ajudam a aumentar o desempenho. No entanto, com o EF5 não é necessário compilar todas as suas consultas, pois o próprio EF irá auto-compilar as consultas. O único problema é que essas consultas podem ser perdidas quando o cache é varrido. Portanto, você ainda deseja manter referências às suas próprias consultas compiladas para aquelas que ocorrem apenas muito raras, mas que são caras. Se você colocar essas consultas em classes estáticas, elas serão compiladas quando forem necessárias pela primeira vez. Isso pode ser muito tarde para algumas consultas, então você pode querer forçar a compilação dessas consultas durante a inicialização do aplicativo.

Visualizações pré-geradas é a outra possibilidade que você mencionou. Especialmente para aquelas consultas que demoram muito para compilar e que não mudam. Dessa forma, você move a sobrecarga de desempenho do tempo de execução para o tempo de compilação. Além disso, isso não apresentará qualquer lag. Mas é claro que essa mudança vai para o banco de dados, então não é tão fácil de lidar. O código é mais flexível.

Não use muita herança TPT (esse é um problema de desempenho geral no EF). Não crie hierarquias de herança muito profundas nem muito largas. Apenas 2 a 3 propriedades específicas para alguma classe podem não ser suficientes para exigir um tipo próprio, mas podem ser tratadas como propriedades opcionais (anuláveis) para um tipo existente.

Não se apegue a um único contexto por muito tempo. Cada instância de contexto tem seu próprio cache de primeiro nível, o que diminui o desempenho à medida que cresce. A criação de contexto é barata, mas o gerenciamento de estado dentro das entidades em cache do contexto pode se tornar caro. Os outros caches (plano de consulta e metadados) são compartilhados entre contextos e morrerão junto com o AppDomain.

Em suma, você deve certificar-se de alocar contextos com frequência e usá-los apenas por um curto período de tempo, de poder iniciar seu aplicativo rapidamente, de compilar consultas que raramente são usadas e fornecer visualizações pré-geradas para consultas que são críticas para o desempenho e frequentemente usadas.

  • Em quais casos o Entity Framework fica "frio" novamente? (Recompilação, Reciclagem, Reinício IIS etc.)

Basicamente, toda vez que você perder seu AppDomain. O IIS reinicia a cada 29 horas , portanto, você nunca pode garantir que terá suas instâncias por perto. Além disso, depois de algum tempo sem atividade, o AppDomain também é encerrado. Você deve tentar subir rapidamente novamente. Talvez você possa fazer parte da inicialização de forma assíncrona (mas cuidado com os problemas de multi-threading). Você pode usar tarefas agendadas que chamam páginas fictícias em seu aplicativo durante os momentos em que não há solicitações para evitar que o AppDomain morra, mas acabará.

Também presumo que quando você altera seu arquivo de configuração ou altera os assemblies, haverá uma reinicialização.

Andreas
fonte
Obrigado Andre, era disso que eu precisava.
Peter
@Andreas Na verdade, mesmo com consultas compiladas estáticas, a primeira execução é muito longa. Existe alguma maneira de aquecê-los além de: Fazer leituras de dados fictícios no início do aplicativo para aquecer, gerar e validar os modelos.
manishKungwani
@Andreas So Entity framework5 precisa ou não? o que é diferente se usá-lo no ef5 (quero dizer, ainda lento ou com pouca massa ou não diferente?)
qakmak
"Static CompiledQuerys são bons porque são rápidos e fáceis de escrever e ajudam a reduzir o desempenho." Desempenho reduzido?
Mathemats de
9

Se você está procurando desempenho máximo em todas as chamadas, deve considerar sua arquitetura com cuidado. Por exemplo, pode fazer sentido pré-armazenar em cache as pesquisas frequentemente usadas na RAM do servidor quando o aplicativo é carregado em vez de usar chamadas de banco de dados em cada solicitação. Essa técnica garantirá tempos de resposta mínimos do aplicativo para os dados comumente usados. No entanto, você deve ter certeza de ter uma política de expiração bem comportada ou sempre limpar seu cache sempre que forem feitas alterações que afetem os dados em cache para evitar problemas de simultaneidade.

Em geral, você deve se esforçar para projetar arquiteturas distribuídas para exigir apenas solicitações de dados baseadas em E / S quando as informações armazenadas localmente em cache se tornarem obsoletas ou precisarem ser transacionais. Qualquer solicitação de dados "durante a transmissão" normalmente levará de 10 a 1000 vezes mais para ser recuperada do que uma local, na recuperação do cache de memória. Este único fato muitas vezes torna as discussões sobre "dados frios vs. quentes" irrelevantes em comparação com a questão dos dados "locais vs. remotos".

Mcstar
fonte
Este é um bom ponto que frequentemente estou ignorando, enquanto sou elogiado sobre o desempenho bruto da estrutura de entidade. Analisarei isso com mais detalhes e pesquisarei mais sobre os princípios do armazenamento em cache. No entanto, "frio vs. quente" em termos de EF ainda é algo que quero entender melhor.
Pedro
2
"Esse único fato costuma tornar as discussões sobre" dados frios vs. quentes "irrelevantes em comparação com a questão dos dados" locais vs. remotos "." Na verdade não. Se você não tiver armazenado em cache localmente (o que não acontecerá inicialmente), você ainda precisará acessar EF e sofrer a dor de inicialização para preparar seu cache. Nos mesmos lugares onde seu cache não foi inicializado, o EF será não inicializado. Portanto, adicionar uma camada de cache pode não ajudar se o único problema for o tempo de inicialização do EF, mas irá adicionar outra camada de complexidade ...
MikeJansen
8

Dicas gerais.

  • Realize registros rigorosos, incluindo o que é acessado e o tempo de solicitação .
  • Execute solicitações fictícias ao inicializar seu aplicativo para inicializar a quente solicitações muito lentas que você escolheu na etapa anterior.
  • Não se preocupe em otimizar a menos que seja um problema real, comunique-se com o consumidor do aplicativo e pergunte. Fique confortável com um ciclo de feedback contínuo, nem que seja para descobrir o que precisa de otimização .

Agora, para explicar por que solicitações fictícias não são a abordagem errada .

  • Menos complexidade - você está aquecendo o aplicativo de uma maneira que funcionará independentemente das mudanças na estrutura e não precisa descobrir APIs / estruturas internas possivelmente funky para fazer isso da maneira certa .
  • Maior cobertura - você está aquecendo todas as camadas de cache de uma vez relacionadas à solicitação lenta.

Para explicar quando um cache fica "frio".

Isso acontece em qualquer camada em sua estrutura que aplique um cache. Há uma boa descrição no topo da página de desempenho .

  • Sempre que um cache precisa ser validado após uma possível alteração que o torna obsoleto, isso pode ser um tempo limite ou mais inteligente (ou seja, alteração no item em cache).
  • Quando um item de cache é removido, o algoritmo para fazer isso é descrito na seção "Algoritmo de remoção de cache" no artigo de desempenho que você vinculou , mas resumidamente.
    • Cache LFRU (menos frequente - usado recentemente) na contagem de ocorrências e idade com um limite de 800 itens.

As outras coisas que você mencionou, especificamente a recompilação e a reinicialização do IIS, limpam partes ou todos os caches na memória.

udoprog
fonte
Esta é outra resposta útil, muito apreciada.
Peter
3

Como você afirmou, use "visualizações pré-geradas", que é tudo o que você realmente precisa fazer.

Extraído do seu link : "Quando as visualizações são geradas, elas também são validadas. Do ponto de vista do desempenho, a grande maioria do custo da geração de visualizações é na verdade a validação das visualizações"

Isso significa que a batida no desempenho ocorrerá quando você construir a montagem do modelo. Seu objeto de contexto irá então pular a "consulta fria" e permanecer responsivo durante o ciclo de vida do objeto de contexto, bem como novos contextos de objeto subsequentes.

A execução de consultas irrelevantes não terá outra finalidade senão consumir recursos do sistema.

O atalho ...

  1. Pule todo aquele trabalho extra de visualizações pré-geradas
  2. Crie seu contexto de objeto
  3. Dispare essa doce consulta irrelevante
  4. Em seguida, basta manter uma referência ao contexto do seu objeto durante o processo (não recomendado).
torta quente
fonte
2

Não tenho experiência neste framework. Mas em outros contextos, por exemplo, Solr, leituras completamente fictícias não serão muito úteis, a menos que você possa armazenar em cache todo o banco de dados (ou índice).

Uma abordagem melhor seria registrar as consultas, extrair as mais comuns dos registros e usá-las para o aquecimento. Apenas certifique-se de não registrar as consultas de aquecimento ou removê-las dos registros antes de continuar.

Estani
fonte