Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo ajuda você a solucionar erros de memória insuficiente no ASP.NET.
Versão original do produto: ASP.NET
Número original do KB: 2020006
Sintomas
Um dos problemas mais comuns que vemos no Atendimento ao Cliente da OutOfMemoryException
Microsoft Por isso, reunimos uma coleção de recursos para ajudar a solucionar problemas e identificar a causa dos problemas de memória.
Antes de abordarmos os detalhes da solução de problemas de um OutOfMemoryException
, é importante entender o que causa esse problema. Ao contrário do que muitos desenvolvedores acreditam, a quantidade de RAM instalada não afeta a possibilidade de um OutOfMemoryException
. Um sistema operacional de 32 bits pode endereçar 4 GB de espaço de endereço virtual, independentemente da quantidade de memória física instalada na caixa. Destes, 2 GB são reservados para o sistema operacional (memória no modo kernel) e 2 GB são alocados para processos no modo de usuário. Os 2 GB alocados para memória no modo kernel são compartilhados entre todos os processos, mas cada processo obtém seus próprios 2 GB de espaço de endereço no modo de usuário. Tudo pressupõe que você não esteja executando com o /3gb
switch ativado.
Quando um aplicativo precisa usar memória, ele reserva uma parte do espaço de endereço virtual e, em seguida, confirma a memória dessa parte. É exatamente o que o GC (coletor de lixo) do .NET Framework faz quando precisa de memória para aumentar os heaps gerenciados. Quando o GC precisa de um novo segmento para o heap de objeto pequeno (onde residem objetos menores que 85 KB), ele faz uma alocação de 64 MB. Quando ele precisa de um novo segmento para o heap de objeto grande, ele faz uma alocação de 16 MB. Essas grandes alocações devem ser atendidas a partir de blocos contíguos dos 2 GB de espaço de endereço com os quais o processo precisa trabalhar. Se o sistema operacional não puder atender à solicitação do GC para um bloco contíguo de memória, ocorrerá um System.OutOfMemoryException
(OOM).
Observação
Um processo de 32 bits em execução em um sistema operacional de 64 bits pode endereçar 4 GB de memória no modo de usuário, e um processo de 64 bits em execução em um sistema operacional de 64 bits pode endereçar 8 TB de memória no modo de usuário, portanto, um OOM em um sistema operacional de 64 bits não é provável. É possível experimentar um OOM em um processo de 32 bits em execução em um sistema operacional de 64 bits, mas geralmente não ocorre até que o processo esteja usando cerca de 3 GB de bytes privados.
Há duas razões pelas quais você pode ver uma condição OOM.
- Seu processo está usando muita memória (normalmente mais de 800 MB em um ambiente de 32 bits).
- O espaço de endereço virtual é fragmentado, reduzindo a probabilidade de que uma alocação grande e contígua seja bem-sucedida.
Também é possível ver uma condição OOM devido a uma combinação de 1 e 2. Para obter mais informações, consulte Solucionando problemas de System.OutOfMemoryExceptions no ASP.NET.
Quando ocorre um OOM, você pode notar um ou mais dos seguintes sintomas:
Seu aplicativo falha. Para obter mais informações, consulte Quem é esse cara OutOfMemory e por que ele faz meu processo travar quando tenho muita memória restante?.
Seu aplicativo pode ter muita memória, conforme indicado pelo Gerenciador de Tarefas ou pelo Monitor de Desempenho.
As solicitações podem levar muito tempo para serem processadas.
No IIS (Serviços de Informações da Internet) 7, você pode usar Solucionando problemas de solicitações com falha usando rastreamento no IIS 7 para solucionar problemas de solicitações de longa execução.
Os usuários podem relatar uma mensagem de erro no aplicativo devido ao OOM.
Quando se trata de determinar a causa de uma condição OOM, você está realmente trabalhando para determinar a causa de uma situação de memória alta ou de um espaço de endereço fragmentado. Embora não possamos documentar todas as possíveis causas dessas situações, existem algumas causas comuns que vemos regularmente.
As informações a seguir descrevem as causas comuns das condições OOM e as resoluções sobre a resolução de cada uma dessas causas.
Concatenação de cadeia de caracteres
As cadeias de caracteres em um aplicativo gerenciado (um aplicativo escrito usando o .NET Framework) são imutáveis. Quando um novo valor é atribuído a uma cadeia de caracteres, é feita uma cópia da cadeia de caracteres existente. E o novo valor é atribuído à nova string. Normalmente não causa problemas. Mas quando um grande número de cadeias de caracteres é concatenado, isso acaba causando muito mais alocações de cadeia de caracteres do que um desenvolvedor pode imaginar. E pode levar ao crescimento da memória e condições OOM.
Para evitar OOM devido à concatenação de cadeia de caracteres, verifique se você está usando a StringBuilder
classe. Para obter mais informações, consulte Como melhorar o desempenho de concatenação de cadeia de caracteres no Visual C#.
Fragmentação no heap gerenciado
O coletor de lixo (GC) em um aplicativo gerenciado compacta os heaps para reduzir a quantidade de fragmentação. No entanto, é possível fixar objetos em um aplicativo gerenciado. Os objetos fixados não podem ser movidos durante a compactação de heap. Isso alteraria o endereço no qual o objeto está localizado. Se um aplicativo fixar um grande número de objetos e/ou fixar objetos por um longo tempo, isso poderá causar fragmentação no heap gerenciado. Isso pode fazer com que o GC aumente o heap gerenciado com mais frequência e cause uma condição OOM.
Trabalhamos para minimizar as condições de OOM devido à fixação desde o .NET Framework 1.0. Melhorias incrementais foram feitas em cada versão. No entanto, ainda existem padrões de design que você pode implementar que serão benéficos se você precisar fixar objetos.
Fragmentação no espaço de endereço virtual (VA)
Cada processo tem uma certa quantidade de memória alocada a ele, e essa memória representa o espaço VA para o processo. Se o espaço VA se tornar fragmentado, isso aumentará a probabilidade de que o GC não consiga obter um grande bloco de memória contígua para aumentar os heaps gerenciados. E isso pode levar a uma condição OOM.
A fragmentação no espaço VA geralmente é causada por um ou mais dos seguintes cenários:
Carregando os mesmos assemblies em vários domínios de aplicativo.
Se você precisar usar um assembly em mais de um aplicativo em execução no mesmo pool de aplicativos, dê um nome forte ao assembly e instale-o no GAC. Ao fazer isso, você garante que o assembly seja carregado no processo apenas uma vez.
Executar um aplicativo em produção com o atributo debug do
<compilation>
elemento definido comotrue
.- O atributo debug do
<compilation>
elemento deve estarfalse
em produção. - Você pode usar a configuração para garantir que a depuração esteja sempre desativada
<deploy retail="true" />
no produto. Para obter mais informações, consulte Elemento de implantação (esquema de configurações do ASP.NET).
- O atributo debug do
Uso de scripts em transformações XSL (eXtensible Style sheet Language) ou criação
XmlSerializers
de arquivos .Nesse caso, assemblies dinâmicos causados por scripts XSLT (Extensible Style sheet Language Transformations) ou
XmlSerializers
.
Retornar grandes conjuntos de dados
Ao usar dados de um banco de dados ou outra fonte de dados, é importante limitar a quantidade de dados retornados. Por exemplo, armazenar em cache um resultado de consulta que retorna uma tabela de banco de dados inteira para evitar o custo de recuperar partes dos dados do banco de dados quando necessário não é uma boa abordagem. Isso pode facilmente causar memória alta e levar a uma condição OOM. Permitir que um usuário inicie uma consulta semelhante é outra maneira comum de criar uma situação de alta memória. Por exemplo, retorne todos os funcionários de uma empresa ou todos os clientes no estado do Texas com um sobrenome começando com a letra S.
Sempre limite a quantidade de dados que podem ser retornados de um banco de dados. Não permita consultas SELECT * FROM. . .
como porque você não tem controle sobre a quantidade de dados exibidos em sua página.
É igualmente importante garantir que você não esteja exibindo um grande resultado de dados em elementos da interface do usuário, como o controle GridView. Além da memória necessária para os dados retornados, você também consumirá grandes quantidades de dados em cadeias de caracteres e em elementos de interface do usuário necessários para renderizar os resultados. Ao implementar a paginação e validar a entrada para que grandes conjuntos de dados não sejam retornados, você pode evitar esse problema.
Executar em um ambiente de produção com rastreamento habilitado
ASP.NET rastreamento é um recurso poderoso para solucionar problemas de aplicativos. Mas nunca deve ser deixado em um ambiente de produção. ASP.NET rastreamento usa estruturas de dados como DataTables
armazenar informações de rastreamento e, com o tempo, pode causar uma condição de memória alta que pode levar ao OOM.
O rastreamento deve ser desabilitado em um ambiente de produção. Você pode fazer isso definindo o enabled
atributo do <trace>
elemento como false em seu arquivo web.config . Habilitar a implantação de varejo usando <deploy retail="true" />
também desabilita o rastreamento em seus aplicativos.
Vazar recursos nativos
Muitos recursos gerenciados também farão uso de recursos nativos. Como o GC não limpa recursos nativos, um desenvolvedor é responsável por implementar e chamar o método Dispose para limpar recursos nativos. Se você estiver usando um tipo que implementa a IDisposable
interface e não chamar o método, corre o Dispose
risco de vazar recursos nativos e causar uma condição OOM.
Esses objetos devem implementar a iDisposable
interface e você deve chamar o Dispose
método nesses objetos quando não precisar mais deles.