Ícone do site Celso Kitamura

Garbage Collector – Conceitos – .NET Framework

Garbage Collector - Conceitos - .NET Framework
5/5 - (2 votes)

Neste primeiro artigo sobre o Garbage Collector vamos ver alguns conceitos importantes para entender o funcionamento deste gerenciador de memória, um dos pilares do .NET Framework.

Quando programamos em C ou C++, muitos objetos requerem que façamos a alocação de seus recursos em sua declaração, antes dos objetos poderem ser utilizados com segurança. Liberar estes recursos de volta ao pool de memória livre também é responsabilidade do programador. Se os recursos não forem liberados, dizemos que o código está com vazamento de memória e mais recursos serão consumidos sem necessidade. Por outro lado, se os recursos forem liberados prematuramente, perda de dados, áreas de memória corrompidas e erros de ponteiros nulos podem ocorrer.

Java e C# previnem estes perigos gerenciando independentemente o tempo de vida de todos os objetos em uso pelo aplicativo.

No Java, o JVM toma conta de liberar memória não utilizada mantendo registro de referências para os recursos alocados. Assim que o JVM detecta que um recurso não é mais referenciado, o recurso é coletado e jogado fora.

Em C#, o Garbage Collector é responsabilidade da CLR (Common Language Runtime) com funcionamento parecido com o JVM. O Garbage Collector checa periodicamente o heap de memória por qualquer objeto sem referência e libera os recursos vinculados a esses objetos.

 

Coleta Automática (Garbage Collector) no .NET

Quando a Microsoft decidiu por uma nova geração de plataforma chamada .NET, sua primeira intenção foi criar uma linguagem fácil de aprender e ter um grande conjunto de APIs. Houve um grande esforço também na coleta de lixo (Garbage Collector) através deste modelo de coleta automática de lixo.

O Garbage Collector foi implementado em uma thread em separado, sempre rodando no back end.

Mas rodar uma thread separada não dá overhead extra? Sim, com certeza. É por isso que a thread do Garbage Collector tem a prioridade mais baixa. Mas quando o Sistema não encontra mais espaço no heap gerenciado, a thread do Garbage Collector recebe prioridade REALTIME (é a mais alta prioridade no Windows) e sai recolhendo todos os objetos que não são mais utilizados.

 

Benefícios do Garbage Collector

 

O heap gerenciado

Depois que o Garbage Collector é inicializado pelo CLR (Commom Language Runtime), ele aloca um segmento de memória para armazenar objetos. Esta memória é chamada de heap gerenciado.

Existe um heap gerenciado para cada processo gerenciado. Todas as threads de um processo alocam memória no mesmo heap.

 

Observação Técnica: O tamanho dos segmentos alocados pelo Garbage Collector é específico de sua implementação e está sujeita a alterações a qualquer momento, incluindo em atualizações periódicas. Seu aplicativo nunca deve fazer suposições sobre ou depender do tamanho de um segmento específico. Muito menos tentar configurar a quantidade de memória disponível para alocação.

 

Quanto menos objetos alocados no heap, menos trabalho o Garbage Collector terá. Por isso, quando você alocar objetos, tente alocar apenas a quantidade de memória necessária.

Quando uma coleta é disparada, o Garbage Collector limpa a memória ocupada por objetos sem uso. Este processo “compacta” objetos em uso, os reorganiza para ficarem juntos e o espaço excedente é removido. Assim o heap fica menor, ocupando menos memória. Isto assegura que objetos alocados juntos continuem juntos no heap gerenciado, preservando sua localização.

A frequência e duração da intervenção das coletas é resultado do volume de alocações e da quantidade de memória restante no heap gerenciado.

O heap é dividido em dois: uma parte com objetos grandes (a partir de 85Kbytes, normalmente arrays) e outro com os menores.

 

Gerações

O heap é organizado em gerações para poder lidar com objetos de vida útil longa e objetos de vida útil curta. A coleta ocorre primeiro com os objetos de vida útil curta, que normalmente ocupam uma pequena parte do heap. Existem 3 gerações de objetos no heap:

Objetos novos alocados formam uma nova geração de objetos e são implicitamente de geração 0, a não ser que sejam objetos grandes. Neste caso eles vão diretamente para o heap de grandes objetos na geração 2.

A maioria dos objetos são coletados na geração 0 e não sobrevivem para a próxima geração.

A coleta ocorre em gerações específicas quando as condições permitem. Coletar uma geração significa coletar objetos nesta geração e em todas as gerações mais novas. Uma coleta na geração 2 também é conhecida como uma coleta total, pois recolhe todos os objetos de todas as gerações (ou seja, todos os objetos do heap gerenciado).

 

Sobreviventes e promoções

Objetos não recolhidos durante uma coleta são conhecidos como sobreviventes e são promovidos para a próxima geração. Objetos sobreviventes de uma coleta na geração 0 são promovidos para a geração 1, objetos sobreviventes de uma coleta na geração 1 são promovidos para a geração 2 e objetos que sobreviventes a uma coleta na geração 2 permanecem na geração 2.

Quando o Garbage Collector percebe que a taxa de sobrevivência em uma geração é alta, ele aumenta o limite de alocações para esta geração, de modo que a próxima coleta consegue uma quantidade substancial de memória recuperada. O CLR faz o balanço continuamente de duas prioridades: não deixar que o conjunto de trabalho de um aplicativo fique muito grande e não deixar a coleta tomar muito tempo.

 

Gerações e segmentos efêmeros

As gerações 0 e 1 também são conhecidos como gerações efêmeras, pelo fato dos objetos neles serem de vida curta.

Gerações efêmeras devem ser alocados no segmento de memória que é conhecido como segmento efêmero. Cada novo segmento adquirido pelo Garbage Collector se torna um novo segmento efêmero e contém os elementos que sobreviveram a coleta da geração 0. O antigo segmento efêmero se torna o novo segmento geração 2.

O tamanho do segmento efêmero varia dependendo do sistema (32 ou 64 bits) e do tipo de Garbage Collector que está em execução. Valores padrão estão na tabela seguinte.

 

32-bit 64-bit
GC de estação 16 MB 256 MB
GC de servidor 64 MB 4 GB
GC de servidor com mais de 4 CPUs lógicos 32 MB 2 GB
GC de servidor com mais de 8 CPUs lógicos 16 MB 1 GB

 

Segmentos efêmeros podem incluir objetos geração 2. Objetos geração 2 podem utilizar múltiplos segmentos (quantas seu processo precisar e a memória suportar).

A quantidade de memória liberada é proporcional ao espaço ocupado pelos objetos inativos.

Agora que estudamos um pouco dos conceitos do Garbage Collector, conseguiremos entender melhor seu funcionamento no próximo artigo da série.

 

Meu e-book Como Aprender a Programar do Absoluto Zero está GRATUITO por tempo limitado!

Olha o link: 👉🏼 http://celsokitamura.com.br/como-aprender-a-programar

Bora aprender a programar!

Sair da versão mobile