Share via


Conceitos básicos de coleta de lixo

No common language runtime (CLR), o coletor de lixo serve como um gerenciador automático de memória. Ele fornece os seguintes benefícios:

  • Permite que você desenvolve seu aplicativo sem a necessidade de liberar memória.

  • Aloca os objetos no heap gerenciado com eficiência.

  • Recupera os objetos que não estão sendo usados, limpa a sua memória e mantém a memória disponível para alocações de futuras. Objetos gerenciados automaticamente obtém conteúdo limpo para iniciar com, não possuem seus construtores inicializar cada campo de dados.

  • Fornece segurança de memória, certificando-se de que um objeto não pode usar o conteúdo de outro objeto.

Este tópico descreve os conceitos básicos de coleta de lixo. Ele contém as seguintes seções:

  • Conceitos básicos de memória

  • Condições para uma coleta de lixo

  • O Heap gerenciado

  • Gerações

  • O que acontece durante uma coleta de lixo

  • Manipulação de recursos não gerenciados

  • Estação de trabalho e a coleta de lixo do servidor

  • Coleta de lixo concorrente

  • Coleta de lixo do plano de fundo

Conceitos básicos de memória

A lista a seguir resume importantes conceitos de memória do CLR.

  • Cada processo tem seu próprio espaço de endereço virtual separado. Todos os processos no mesmo computador compartilham a mesma memória física e compartilham o arquivo de página, se houver.

  • Por padrão, nos computadores de 32 bits, cada processo tem um espaço de endereço virtual do modo de usuário de 2 GB.

  • Como desenvolvedor de aplicativos, você pode trabalha somente com o espaço de endereço virtual e nunca manipular a memória física diretamente. O coletor de lixo aloca e libera memória virtual para você no heap gerenciado.

    Se você estiver escrevendo código nativo, você usar funções do Win32 para trabalhar com o espaço de endereço virtual. Essas funções alocar e liberar memória virtual para você em nativo pilhas.

  • Memória virtual pode estar em três estados:

    • Livre. O bloco de memória não possui referências a ele e está disponível para alocação.

    • Reservado. O bloco de memória está disponível para uso e não pode ser usado para qualquer outra solicitação de alocação. No entanto, é possível armazenar dados para o bloco de memória até que ela seja confirmada.

    • O compromisso. O bloco de memória é atribuído ao armazenamento físico.

  • Espaço de endereço virtual pode fragmentado. Isso significa que há livre bloqueia, também conhecido como orifícios, no espaço de endereço. Quando a alocação de memória virtual é solicitada, o Gerenciador de memória virtual tem que localizar um único bloco livre que seja grande o suficiente para satisfazer a solicitação de alocação. Mesmo que você tenha 2 GB de espaço livre, a alocação de 2 GB de requer conseguirão a menos que todo esse espaço esteja em um bloco de endereço único.

  • Você pode executar fora da memória, se você ficar sem espaço de endereço virtual para reservar ou espaço físico para confirmar.

Seu arquivo de página é usado, mesmo se a pressão de memória física (isto é, a demanda para a memória física) é baixa. Na primeira vez em que a pressão de memória física é alta, o sistema operacional deve liberar espaço na memória física para armazenar dados e faz backup de alguns dos dados que está na memória física para o arquivo de página. Que dados não são paginados até que ele é necessário, portanto, é possível encontrar a paginação em situações onde a pressão de memória física é muito baixa.

Voltar ao topo

Condições para uma coleta de lixo

Coleta de lixo ocorre quando uma das seguintes condições for verdadeira:

  • O sistema tem pouca memória física.

  • A memória que é usada por objetos alocados no heap gerenciado ultrapassa o limite aceitável. Isso significa que um limite de uso aceitável de memória foi excedido no heap gerenciado. Esse limite é ajustado continuamente, como o processo é executado.

  • O GC.Collect método é chamado. Em quase todos os casos, você não precisará chamar esse método, porque o coletor de lixo é executado continuamente. Este método é usado principalmente para situações específicas e testes.

Voltar ao topo

O Heap gerenciado

Depois que o coletor de lixo é inicializado pelo CLR, ele aloca um segmento de memória para armazenar e gerenciar objetos. Essa memória é chamada de heap gerenciado, ao contrário de um heap nativa no sistema operacional.

Há uma pilha gerenciada para cada processo gerenciado. Todos os segmentos no processo de alocar os objetos na mesma pilha.

Para reservar a memória, o coletor de lixo chamar o Win32 VirtualAlloc função e um segmento de reserva de memória de uma vez para aplicativos gerenciados. O coletor de lixo também reserva segmentos conforme necessário e libera os segmentos de volta para o sistema operacional (depois de limpá-los de quaisquer objetos) chamando o Win32 VirtualFree função.

Menos objetos alocados na pilha, menos trabalho que o coletor de lixo tem a ver. Quando você aloca objetos, não use valores de arredondada excederem suas necessidades, como alocar uma matriz de 32 bytes quando você precisar apenas de 15 bytes.

Quando uma coleta de lixo é disparada, o coletor de lixo recupera a memória ocupada por objetos mortos. O processo de recuperação compacta objetos ao vivo para que eles são movidos em conjunto e o espaço de inatividade é removido, tornando o heap menores. Isso garante que os objetos que são alocados juntos permaneçam juntas no heap gerenciado, para preservar sua localidade.

Intrusiveness (freqüência e duração) de coletas de lixo é o resultado do volume de alocações e a quantidade de memória sobrevivida no heap gerenciado.

A pilha pode ser considerada como o acúmulo de pilhas de dois: a pilha de objetos grandes e pilha de objetos pequenos.

A pilha de objetos grandes contém objetos 85.000 bytes e maiores. Objetos muito grandes na pilha de objetos grandes são normalmente matrizes. É raro para um objeto de instância a ser extremamente grandes.

Voltar ao topo

Gerações

A pilha é organizada em gerações para que ele pode manipular objetos de vida longa e curta duração. Principalmente, coleta de lixo ocorre com a recuperação de objetos de curta duração que geralmente ocupam apenas uma pequena parte da pilha. Há três gerações de objetos na heap:

  • Geração 0. Esta é a mais nova geração e contém objetos de curta duração. Um exemplo de um objeto de curta duração é uma variável temporária. Coleta de lixo ocorre com mais freqüência nesta geração.

    Objetos alocados recentemente uma nova geração de objetos de formulário e implicitamente são coleções de geração 0, a menos que sejam objetos grandes, caso em que eles ir no heap de objeto grande em uma coleção de geração 2.

    A maioria dos objetos são reivindicados para coleta de lixo na geração 0 e não sobrevivem à próxima geração.

  • Geração 1. Esta geração contém objetos de curta duração e serve como um buffer entre objetos de curta duração e vida longa.

  • Geração 2. Esta geração contém objetos de vida longa. Um exemplo de um objeto de longa vida é um objeto em um aplicativo de servidor que contém os dados estáticos que está vivo para a duração do processo.

Coletas de lixo ocorrem em gerações específicas, como as condições o permitirem. Coletar uma geração significa coletar objetos na geração e todas as suas gerações mais jovens. Uma coleta de lixo da geração 2 também é conhecido como uma coleta de lixo completa, porque ele recupera todos os objetos em todas as gerações (ou seja, todos os objetos no heap gerenciado).

Sobrevivência e promoções

Objetos que não são recuperados em uma coleta de lixo são conhecidos como sobreviventes e são promovidos à próxima geração. Objetos que sobrevivem a uma coleta de geração 0 lixo são promovidos para a geração 1. objetos que sobrevivem a uma coleta de geração 1 lixo são promovidos à geração 2; e os objetos que sobrevivem a uma coleta de lixo da geração 2 permanecem na geração 2.

Quando o coletor de lixo detecta que a taxa de sobrevivência é alta em uma geração, ela aumenta o limite de alocações para geração, portanto, a próxima coleta obtém um tamanho substancial de memória recuperado. O CLR equilibra continuamente a duas prioridades: não permitir que um aplicativo muito grande de get de conjunto de trabalho e não permitindo a coleta de lixo levar muito tempo.

Segmentos e gerações efêmeras

Porque os objetos em gerações 0 e 1 são de curta duração, essas gerações são conhecidas como as gerações efêmeras.

Gerações efêmeras devem ser alocadas no segmento de memória que é conhecido como o segmento efêmero. Cada novo segmento adquirido pelo coletor de lixo se torna o novo segmento efêmero e contém os objetos que sobreviveram a uma coleta de lixo 0 de geração. O antigo segmento efêmero torna-se o segmento de nova geração 2.

O segmento efêmero pode incluir objetos da geração 2. Objetos da geração 2 podem usar vários segmentos (tantas quantas requer que seu processo e memória permite).

A quantidade de memória liberada a partir de uma coleta de lixo efêmera é limitada ao tamanho do segmento efêmero. A quantidade de memória é liberada é proporcional ao espaço que foi ocupado por objetos inativos.

Voltar ao topo

O que acontece durante uma coleta de lixo

Uma coleta de lixo tem as seguintes fases:

  • Uma fase de marcação que localiza e cria uma lista de todos os objetos ao vivo.

  • Fase realocando atualiza as referências aos objetos que serão compactadas.

  • Fase de compactação que recupera o espaço ocupado pelos objetos inativos e compacta os objetos sobreviventes. A fase de compactação move objetos que sobreviveram a uma coleta de lixo em direção ao final do segmento mais antigo.

    Porque as coletas da geração 2 podem ocupar vários segmentos, os objetos são promovidos a geração 2 podem ser movidos para um segmento mais antigo. Geração 1 e sobreviventes da geração 2 podem ser movidos para um segmento diferente, porque eles são promovidos para a geração 2.

    A pilha de objetos grandes não é compactada, porque isso aumentaria o uso de memória por um período de tempo inaceitável.

O coletor de lixo usa as informações a seguir para determinar se os objetos são ao vivo:

  • A pilha de raízes. A pilha de variáveis fornecidas pelo compilador do just-in-time (JIT) e o movimentador de pilha.

  • Alças de coleta de lixo. Trata-se de que o ponto de objetos gerenciados e que pode ser alocado pelo código do usuário ou pelo common language runtime.

  • Dados estáticos. Objetos estáticos em domínios de aplicativo que poderiam estar fazendo referência a outros objetos. Cada domínio de aplicativo mantém registro de seus objetos estáticos.

Antes de inicia a uma coleta de lixo, todos os threads gerenciados são suspensos, exceto para o segmento que acionou a coleta de lixo.

A ilustração a seguir mostra um segmento que aciona uma coleta de lixo e faz com que outros threads a ser suspenso.

Segmento que aciona uma coleta de lixo

Quando um <>>thread dispara uma coleta de lixo

Voltar ao topo

Manipulação de recursos não gerenciados

Se os objetos gerenciados fazer referência a objetos não gerenciados usando seus identificadores de arquivo nativo, você tem explicitamente liberem objetos gerenciados, porque o coletor de lixo rastreia a memória somente no heap gerenciado.

Os usuários do seu objeto gerenciado não podem dispor os recursos nativos usados pelo objeto. Para executar a limpeza, você pode tornar seu objeto gerenciado finalizáveis. Finalização consiste em ações de limpeza que você executar quando o objeto não está mais em uso. Quando o seu objeto gerenciado seja eliminado, ele executa ações de limpeza que são especificadas em seu método do finalizador.

Quando um objeto finalizável é descoberto estar inoperante, seu finalizador é colocada em uma fila para que suas ações de limpeza são executadas, mas o próprio objeto seja promovido para a próxima geração. Portanto, você precisa esperar até a próxima coleta de lixo ocorre nessa geração (que não necessariamente a próxima coleta de lixo) para determinar se o objeto foi recuperado.

Voltar ao topo

Estação de trabalho e a coleta de lixo do servidor

O coletor de lixo é o ajuste automático e pode trabalhar em uma ampla variedade de cenários. A única opção que você pode definir é o tipo de coleta de lixo, com base nas características da carga de trabalho. O CLR fornece os seguintes tipos de coleta de lixo:

  • Coleta de lixo de estação de trabalho, que é para todas as estações de trabalho do cliente e PCs autônomos. Esta é a configuração padrão para o <gcServer> elemento no esquema de configuração de tempo de execução.

    Coleta de lixo da estação de trabalho pode ser simultâneas ou não-simultâneo. Coleta de lixo simultâneo permite que os threads gerenciados continuar as operações durante uma coleta de lixo.

    Começando com o .NET Framework versão 4, coleta de lixo do plano de fundo substitui coleta de lixo simultâneo. 

  • Coleta de lixo de servidor, que é destinada a aplicativos de servidor que precisam de escalabilidade e alta taxa de transferência.

As ilustrações a seguir mostra os segmentos dedicados que executam a coleta de lixo em um servidor.

Coleta de lixo do servidor

Threads de coleta de lixo do servidor

Configurando a coleta de lixo

Você pode usar o <gcServer> elemento do esquema de configuração de tempo de execução para especificar o tipo de coleta de lixo você deseja que o CLR para realizar. Quando este elemento enabled atributo está definido como false (padrão), o CLR executa coleta de lixo de estação de trabalho. Ao definir o enabled atributo para true, o CLR realiza coleta de lixo do servidor.

Coleta de lixo simultâneos é especificada com o <gcConcurrent> elemento do esquema de configuração de tempo de execução. A configuração padrão é enabled. Coleta de lixo simultânea só está disponível para coleta de lixo da estação de trabalho e não tem efeito sobre a coleta de lixo do servidor.

Você também pode especificar a coleta de lixo do servidor com as interfaces de hospedagem não gerenciadas. Observe que o ASP.NET e SQL Server habilitam coleta de lixo do servidor automaticamente se o seu aplicativo é hospedado em um desses ambientes.

Comparando a estação de trabalho e a coleta de lixo do servidor

Considerações sobre Threading e desempenho para coleta de lixo da estação de trabalho:

  • A coleção ocorre no thread do usuário que disparou a coleta de lixo e permanece com a mesma prioridade. Como os threads de usuário normalmente são executados com prioridade normal, o coletor de lixo (que é executado em um segmento de prioridade normal) têm de competir com outros segmentos para o tempo de CPU.

    Os threads que estejam executando o código nativo não são suspensos.

  • Coleta de lixo da estação de trabalho é sempre usada em um computador que tem apenas um processador, independentemente do <gcServer> configuração. Se você especificar a coleta de lixo do servidor, o CLR usa coleta de lixo da estação de trabalho com simultaneidade desabilitada.

Considerações sobre Threading e desempenho para coleta de lixo do servidor:

  • A coleção ocorre em vários segmentos dedicados que executam em THREAD_PRIORITY_HIGHEST nível de prioridade.

  • Um thread dedicado para realizar a coleta de lixo e uma pilha são fornecidos para cada CPU e pilhas são coletadas, ao mesmo tempo. Cada pilha contém uma pilha de objetos pequenos e uma pilha de objetos grandes e all heaps podem ser acessados pelo código do usuário. Objetos em diferentes heaps podem referir-se uns aos outros.

  • Como vários segmentos de coleta de lixo trabalham juntos, coleta de lixo do servidor é mais rápida do que a coleta de lixo da estação de trabalho na mesma pilha de tamanho.

  • Coleta de lixo do servidor geralmente possui segmentos de tamanho maiores.

  • Coleta de lixo do servidor pode ser que consomem muitos recursos. Por exemplo, se você tiver 12 processos executados em um computador que possui 4 processadores, haverá 48 threads de coleta de lixo dedicado se eles estiverem todos usando coleta de lixo do servidor. Em uma situação de carga de memória alta, se todos os processos começar a fazer a coleta de lixo, o coletor de lixo terá 48 threads para agendar.

Se você estiver executando centenas de instâncias de um aplicativo, considere o uso de coleta de lixo da estação de trabalho com a coleta de lixo simultâneas desabilitada. Isso resultará em menos alternância de contexto, que pode melhorar o desempenho.

Voltar ao topo

Coleta de lixo concorrente

Na coleta de lixo da estação de trabalho, você pode habilitar a coleta de lixo simultâneas, o que permite que os segmentos a serem executados simultaneamente com um thread dedicado que realiza a coleta de lixo para a maioria da duração da coleção. Essa opção afeta apenas as coletas de lixo na geração 2; gerações 0 e 1 são sempre não-simultâneo porque eles término muito rápido.

Coleta de lixo simultâneo permite que os aplicativos interativos ser mais responsivo, minimizando as pausas para uma coleção. Threads gerenciados podem continuar a executar a maioria das vezes durante a execução do thread de coleta de lixo simultâneas. Isso resulta em menores pausas enquanto está ocorrendo uma coleta de lixo.

Para melhorar o desempenho quando vários processos estão em execução, desabilite a coleta de lixo simultâneas.

Coleta de lixo simultâneos é realizada em um thread dedicado. Por padrão, o CLR executa a coleta de lixo da estação de trabalho com a coleta de lixo simultâneas ativada. Isso é verdadeiro para os computadores de processador único e vários processadores.

Sua capacidade de alocar pequenos objetos na heap durante uma coleta de lixo simultâneas é limitada pelos objetos deixados no segmento efêmero quando uma coleta de lixo simultâneos é iniciado. Assim que chegar ao final do segmento, você terá que aguardar a coleta de lixo simultâneas terminar enquanto threads gerenciados que precisam fazer alocações de objeto pequeno são suspensos.

Coleta de lixo simultâneas tem um conjunto de trabalho um pouco maior (em comparação com a coleta de lixo de não-simultâneo), porque você pode alocar objetos durante a coleta simultânea. No entanto, isso pode afetar o desempenho, porque os objetos que você alocar tornam-se parte do seu conjunto de trabalho. Essencialmente, a coleta de lixo simultâneas negócios alguns CPU e memória para pausas mais curtas.

A ilustração a seguir mostra a coleta de lixo de simultâneas realizada em um thread dedicado separado.

Coleta de lixo simultâneas

Segmentos simultâneos de coleta de lixo

Voltar ao topo

Coleta de lixo do plano de fundo

Na coleta de lixo do plano de fundo, efêmeras gerações (0 e 1) são coletadas conforme necessário, enquanto a coleta de geração 2 está em andamento. Não há nenhuma configuração de coleta de lixo do plano de fundo; ele é ativado automaticamente com a coleta de lixo simultâneas. Coleta de lixo do plano de fundo é uma substituição para coleta de lixo simultâneas. Como com coleta de lixo simultâneas, coleta de lixo do plano de fundo é executada em um thread dedicado e é aplicável somente a coleções de geração 2.

Observação

Coleta de lixo do plano de fundo só está disponível no .NET Framework 4 e versões posteriores.

Uma coleção em gerações efêmeras durante a coleta de lixo do plano de fundo é conhecida como coleta de lixo do primeiro plano. Quando ocorrem de coletas de lixo do primeiro plano, todos os threads gerenciados são suspensos.

Quando a coleta de lixo em segundo plano está em andamento e você tiver alocado suficiente objetos na geração 0, o CLR realiza uma geração 0 ou a coleta de lixo da geração 1 de primeiro plano. O segmento de coleta de lixo dedicado de plano de fundo verifica em pontos de seguros freqüentes para determinar se há uma solicitação de coleta de lixo do primeiro plano. Se houver, a coleção de plano de fundo suspende próprio para que seja feita a coleta de lixo do primeiro plano. Após a coleta de lixo do primeiro plano, retomar o thread de coleta de lixo do plano de fundo dedicado e os threads de usuário.

Coleta de lixo do plano de fundo remove restrições de alocação, impostas pela coleta de lixo simultâneas, porque as coletas de lixo efêmeras podem ocorrer durante a coleta de lixo do plano de fundo. Isso significa que a coleta de lixo do plano de fundo pode remover objetos mortos em gerações efêmeras e também é possível expandir o heap se for necessário durante uma coleta de lixo 1 de geração.

Coleta de lixo do plano de fundo não está disponível atualmente para coleta de lixo do servidor.

Voltar ao topo

Consulte também

Conceitos

Coleta de Lixo