Coisas rápidas para marcar quando você experimenta altos níveis de memória em ASP.NET

Este artigo descreve as coisas rápidas a serem marcar quando você experimenta memória alta no Microsoft ASP.NET.

Versão original do produto: ASP.NET
Número original do KB: 893660

Este artigo começará com alguns problemas comuns, ações para solucionar essas questões e uma breve explicação de por que essas situações podem causar problemas.

ASP.NET coluna Voz de Suporte

Na coluna Voz de Suporte de abril de 2005, inadvertidamente fornecemos um link para o arquivo errado. Em vez de vincular a um download para o serviço Web, vinculamos ao arquivo XML retornado pelo serviço Web. Esse link foi corrigido. Se você quiser examinar o artigo com o arquivo correto anexado, confira Atualizações de página dinâmicas usando XMLHTTP.

O que é considerado memória alta

Obviamente, essa pergunta depende do volume e da atividade de aplicativos específicos. Em geral, a memória alta é quando a memória do ASP.NET processo de trabalho (Aspnet_wp.exe) ou do processo de trabalho do IIS (Serviços de Informações da Internet) (W3wp.exe) está aumentando consistentemente e não está voltando a um nível confortável.

Em termos gerais, um nível confortável seria inferior a 600 MB no espaço padrão de endereço de memória do usuário de 2 GB. Depois que o nível de memória é maior que esse nível confortável, estamos fazendo menos do que deveríamos. Esse comportamento pode afetar outros aplicativos que estão em execução no sistema.

A chave é entender que alguns aplicativos exigem mais memória do que outros. Se você estiver excedendo esses limites, poderá adicionar mais memória ou adicionar outro servidor ao seu farm da Web (ou considerar um farm da Web). A criação de perfil também é recomendada nesses casos. Ele pode permitir que os desenvolvedores criem aplicativos mais enxutos. Neste artigo, estamos analisando uma situação em que você vê consistentemente o aumento da memória até que o servidor pare de executar.

Aplicativo configurado para depuração

Um dos motivos para a memória alta que vemos aqui no Suporte é quando você tem depuração, rastreamento ou ambos habilitados para seu aplicativo. Habilitar a depuração e o rastreamento é uma necessidade quando você desenvolve seu aplicativo. Por padrão, ao criar seu aplicativo no Visual Studio .NET, você verá o seguinte atributo definido em seu arquivoWeb.config :

<compilation
 ...
 debug="true"
 />

ou

 <trace
 enabled="true"
 ...
 />

Além disso, ao fazer um build final do aplicativo, certifique-se de fazê-lo no modo Depuração, não no modo de depuração. Depois de estar em produção, a depuração não deve mais ser necessária. Isso pode realmente retardar seu desempenho e comer sua memória. Definir esse atributo significa que você altera algumas coisas sobre como lida com seu aplicativo.

Primeiro, o compilado em lote será desabilitado, mesmo que seja definido nesse compilation elemento. Isso significa que você cria um assembly para cada página em seu aplicativo para que você possa invadiu. Esses assemblies podem ser espalhados aleatoriamente pelo espaço de memória, dificultando a localização do espaço contíguo para alocar memória.

Em segundo lugar, o executionTimeout atributo (<elemento httpRuntime>) é definido como um número alto, substituindo o padrão de 90 segundos. Tudo bem ao depurar, porque você não pode ter o tempo limite do aplicativo enquanto passa pacientemente pelo código para encontrar seus erros. No entanto, é um risco significativo na produção. Isso significa que, se você tiver uma solicitação desonesto por qualquer motivo, ele se manterá em um thread e continuará qualquer comportamento prejudicial por dias, em vez de alguns minutos.

Por fim, você criará mais arquivos na pasta de arquivos Temporary ASP.NET . E o (System.Diagnostics Namespace é adicionado a todo código gerado, o System.Diagnostics.DebuggableAttribute que pode causar degradação de desempenho.

Se você não receber mais nada deste artigo, espero que obtenha essa informação. Deixar a depuração habilitada é ruim. Vemos esse comportamento com muita frequência, e é tão fácil mudar. Lembre-se de que pode ser definido no nível da página. Verifique se todas as páginas não estão definindo.

Concatenação de cadeia de caracteres

Há aplicativos que criam a saída HTML usando o código do lado do servidor e apenas criando uma cadeia de caracteres HTML grande para enviar ao navegador. Tudo bem, mas se você estiver construindo a cadeia de caracteres usando + e & concatenando, talvez não esteja ciente de quantas cadeias de caracteres grandes você está construindo. Por exemplo:

string mystring = "<html>";
mystring = mystring + "<table><tr><td>";
mystring = mystring + "First Cell";
mystring = mystring + "</td></tr></table>";
mystring = mystring + "</html>";

Este código parece inofensivo o suficiente, mas aqui está o que você está armazenando na memória:

<html>
<html><table><tr><td>
<html><table><tr><td>First Cell
<html><table><tr><td>First Cell</td></tr></table>
<html><table><tr><td>First Cell</td></tr></table></html>

Você pode pensar que está apenas armazenando a última linha, mas está armazenando todas essas linhas. Você pode ver como ele pode sair do controle, especialmente quando você está construindo uma grande tabela, talvez por loop através de um grande conjunto de registros. Se é o que você está fazendo, use nossa System.Text.StringBuilder classe, para que você armazene uma cadeia de caracteres grande. Consulte Usar o Visual C# para melhorar o desempenho da concatenação de cadeia de caracteres

.NET Framework Service Pack 1 (SP1)

Se você ainda não estiver executando o .NET Framework SP1, instale esse SP se estiver enfrentando problemas de memória. Não vou entrar em detalhes, mas basicamente, com o SP1 estamos alocando memória de uma maneira muito mais eficiente. Basicamente, estamos alocando 16 MB por vez para objetos grandes em vez de 64 MB por vez. Todos nós nos mudamos, e todos sabemos que podemos empacotar muito mais em um carro ou caminhão se estivermos usando muitas caixas pequenas em vez de algumas caixas grandes. É a ideia aqui.

Não tenha medo de reciclar periodicamente

Reciclamos pools de aplicativos no IIS a cada 29 horas por padrão. O processo Aspnet_wp.exe continuará até que você termine a tarefa, reinicie o IIS ou reinicie o computador. Esse comportamento significa que esse processo pode estar em execução por meses. É uma boa ideia que alguns aplicativos reiniciem o processo de trabalho a cada dois dias ou mais, em um momento conveniente.

Perguntas a serem feitas

As anteriores eram todas as coisas que você pode corrigir rapidamente. No entanto, se você estiver enfrentando problemas de memória, faça estas perguntas a si mesmo:

  • Estou usando muitos objetos grandes? Mais de 85.000 KB são armazenados em um grande heap de objetos.

  • Estou armazenando objetos no estado de sessão? Esses objetos ficarão na memória por muito mais tempo do que se você usá-los e eliminá-los.

  • Estou usando o Cache objeto? Quando é usado com sabedoria, é um grande benefício para o desempenho. Mas quando ele é usado de forma imprudente, você acaba com muita memória usada que nunca é lançada.

  • Estou retornando recordsets muito grande para um aplicativo Web? Ninguém quer examinar 1.000 registros em uma página da Web. Você deve estar projetando seu aplicativo para nunca obter mais de 50 a 100 registros em uma viagem.

Depuração

Não vou entrar na configuração do WinDbg. Mas você pode usar os comandos a seguir para ver o que exatamente está em sua memória, se quiser solucionar problemas mais complicados.

!eeheap -gc

Este comando mostrará a quantidade de memória gerenciada que você tem. Se esse valor for alto, há algo que seu código gerenciado está criando.

!dumpheap -stat

Esse comando levará um bom tempo para ser executado, mesmo que sua memória seja grande. Mas esse comando lhe dará uma lista de todos os objetos, quantos de cada tipo e quanta memória cada um está usando. (Por exemplo, para a StringBuilder classe, você verá muitos System.String objetos)

Depois de encontrar um objeto que leva muita memória, procure mais usando o seguinte comando:

!do <addr>

Você pode obter o endereço do objeto que está procurando no dumpheap comando.

Tentaremos incorporar mais maneiras de usar essa ferramenta de diagnóstico para situações específicas nessas colunas. Deixe-nos saber se estamos fazendo um bom trabalho!

Artigos de memória e desempenho

Noções básicas e dicas de desempenho do coletor de lixo

Desenvolvendo aplicativos High-Performance ASP.NET

ASP.NET Monitoramento de Desempenho e Quando Alertar Administradores

Aprimorando o desempenho e a escalabilidade do aplicativo .NET