Coleta de lixo
Python, Java, Go e JavaScript não exigem que você chame free(). Um coletor de lixo (garbage collector) rastreia automaticamente quais objetos ainda são alcançáveis e libera os demais. Mas não é mágica — há custo, pausa e algoritmos.
Lixo = objeto que nenhum código pode mais acessar
Um objeto é "lixo" quando não existe mais nenhum caminho a partir de uma variável ativa que chegue até ele. O programa não pode usá-lo, mas ele ainda ocupa memória. O trabalho do GC é identificar esses objetos e liberar o espaço.
O modelo mental é um grafo: os nós são objetos no heap, as arestas são referências entre eles. As raízes são os pontos de entrada — variáveis globais e frames de função ativos na stack. Um objeto é alcançável se existe um caminho das raízes até ele. Tudo que for inalcançável é lixo.
Mark-and-Sweep ao vivo
Clique em "Marcar" para ver o GC fazer DFS a partir das raízes, colorindo objetos alcançáveis (verde) e inalcançáveis (vermelho). Depois "Varrer" para coletar os inalcançáveis.
Mark-and-Sweep
// Mark-and-Sweep: o algoritmo GC clássico // 1. PAUSA o programa ("stop-the-world") // 2. MARCA: DFS/BFS a partir das raízes // Raízes = variáveis globais + variáveis nos stack frames ativos def mark(obj): if obj.marcado: return obj.marcado = True for ref in obj.referencias: mark(ref) // percorre todo o grafo de objetos for raiz in todas_as_raizes: mark(raiz) // 3. VARRE: percorre o heap e coleta os NÃO marcados for obj in todo_o_heap: if not obj.marcado: liberar(obj) // inalcançável → lixo // 4. RETOMA o programa
Contagem de referências
// Contagem de referências: alternativa ao mark-and-sweep // Cada objeto mantém um contador: quantas referências apontam para ele? a = Obj() // rc(a) = 1 b = a // rc(a) = 2 b = None // rc(a) = 1 a = None // rc(a) = 0 → liberado IMEDIATAMENTE // Vantagem: sem "stop-the-world", liberação determinística // Desvantagem fatal: ciclos nunca chegam a rc = 0 a = Obj(); b = Obj() a.outro = b; b.outro = a // ciclo! a = None; b = None // rc(a_obj) = 1 (b_obj aponta), rc(b_obj) = 1 (a_obj aponta) // Nenhum chega a 0 → leak permanente // Solução: GC cíclico adicional (CPython faz isso) // Swift/Rust: weak references quebram ciclos manualmente
Implementando um GC simples
Mini projeto: em Python, simule um grafo de objetos com um dicionário de listas de adjacência. Implemente mark_and_sweep(roots, graph) que retorna o conjunto de nós coletados. Teste com casos que incluam ciclos e confirme que mark-and-sweep os coleta enquanto contagem de referências falha.
Projeto principal: em C, implemente um GC Cheney (cópia de objetos) simplificado: dois semiespaços de memória. Durante a coleta, todos os objetos alcançáveis são copiados para o outro semiespaço (compactando o heap no processo). O semiespaço antigo é descartado inteiro. Meça a velocidade de alocação vs. mark-and-sweep.
Desafio extra: estude o código-fonte do GC do CPython (Modules/gc.c) ou do Go (runtime/mgc.go). Documente em um texto curto: qual algoritmo é usado, como ciclos são detectados, e como a implementação gerencia as pausas. Qual é a principal troca (tradeoff) de cada abordagem?
Teste sua intuição
Onde você encontra isso
JVM — GC geracional e ZGC
A JVM de produção (OpenJDK) oferece vários coletores: G1 (latência balanceada), ZGC (pausas sub-milissegundo mesmo com heaps de TB), Shenandoah (concurrent compaction). Aplicações como Elasticsearch e Kafka são ajustadas com flags de GC como -Xmx, -XX:+UseZGC para controlar a troca entre throughput e latência.
Go — GC tricolor concorrente
O GC do Go roda concorrentemente usando um algoritmo tricolor (branco/cinza/preto) com barreiras de escrita. Latências de GC caíram de centenas de ms na versão 1.0 para sub-milissegundo em 1.17+. Go não tem GC geracional — a escolha simplifica a implementação mas limita throughput em cargas com muitos objetos de curta vida.
V8 — GC do JavaScript
O V8 (Chrome, Node.js) usa Orinoco: um GC geracional, paralelo e concorrente. O young space usa Cheney copying (compacta e é rápido); o old space usa mark-compact. O GC do V8 é um projeto de engenharia próprio — partes dele (como Scavenge) são publicadas como artigos acadêmicos e influenciam outros projetos.