Gargabe Collector no Golang


O Garbage Collector (GC) do Go é um coletor concorrente de baixa latência. Seu objetivo principal é minimizar as pausas do programa (STW – Stop-The-World) enquanto libera memória não utilizada. Usa a técnica tri-color and sweep e não geracional.
Tri-color Mark And Sweep
Utiliza algoritmo de marcação e varredura em três cores ( branco, cinza e preto) para gerenciar objetos.
- Branco: objeto não marcado/não visitado (candidato a coleta).
- Cinza: objeto marcado, mas ainda não totalmente escaneado (faltam referências para analisar).
- Preto: objeto marcado e totalmente escaneado (suas referências já foram processadas).
Não Geracional
- Todos os objetos são tratados uniformemente, independente de idade
- Essa escolha simplifica o coletor e evita a necessidade de barreiras de escrita específicas entre gerações. Na prática, o Go compensa isso com um GC concorrente, que executa a maior parte da marcação enquanto a aplicação continua rodando, reduzindo ao mínimo as pausas STW (Stop-The-World).
Write Barrier
O write barrier é o “guarda de trânsito” que observa toda modificação de ponteiro durante o GC e garante que nenhum objeto vivo seja acidentalmente coletado, mantendo a invariante: um objeto BLACK nunca aponta para um WHITE sem que esse WHITE seja re-escaneado.
Problema sem Write Barrier
No GC concorrente do Go, o coletor executa enquanto as goroutines continuam alterando objetos na memória. Sem a write barrier, um objeto já escaneado poderia receber uma nova referência para outro objeto, mas o GC não perceberia essa mudança. Assim, esse objeto ainda em uso poderia ser coletado incorretamente. A write barrier resolve isso interceptando escritas de ponteiros e garantindo que novas referências sejam marcadas pelo GC.
Objetos Alcançáveis
São objetos que podem ser acessados direta ou indiretamente a partir de referências existentes nos pontos de entrada do programa.
Se o GC consegue “chegar” até um objeto seguindo referências, então esse objeto é considerado alcançável e não pode ser liberado.
Roots:
As roots são os pontos iniciais usados pelo Garbage Collector para iniciar a busca de objetos alcançáveis.
No Go, normalmente incluem:
- Variáveis globais
- Variáveis locais ativas nas stacks
- Registradores da CPU
- Alguns ponteiros mantidos pelo runtime
O GC começa a partir dessas roots e percorre recursivamente todas as referências encontradas.
package main
type Address struct {
City string
}
type User struct {
Name string
Address *Address
}
var global = &User{Name: "Rafael"} // root global
func main() {
local := &Address{City: "SP"} // root local (stack)
global.Address = local
}Nesse caso:
Globalé uma root globalLocalé uma root local da stack- O objeto
Addressé alcançável porque existe uma referência para ele - Enquanto essas referências existirem, o GC não libera os objetos
Quando um objeto vira lixo
Um objeto vira garbage quando não existe mais nenhum caminho de referências partindo das roots até ele.
Exemplo:
Com nil no objeto
func main() {
user := &User{Name: "Rafael"}
user = nil
}outro exemplo de vários. Quando a função termina, as referências locais desaparecem.
func createUser() {
user := &User{Name: "Rafael"}
fmt.Println(user.Name)
}
func main() {
createUser()
// aqui não existe mais nenhuma referência para user
}Fluxo do GC do Go
- 1. STW (Stop-The-World) – Mark Setup
- 1.1 Inicializa a marcação (roots, estado do GC, write barrier ligada)
- 2. Marking Work (concorrente)
- 2.1 Usa workers de GC (meta de ~25% da CPU disponível para marking)
- 2.2 Mark assist: goroutines que alocam ajudam a marcar
- 3. Mark Termination (STW)
- 3.1 Finaliza a marcação pendente
- 3.2 Desliga a write barrier
- 4. Sweeping (concorrente)
- 4.1 Identifica e libera memória de objetos não marcados
- 4.2 Varredura on-demand (lazy sweep)
Variável (GOGC)
É o principal mecanismo para ajustar a agressividade do GC. Por padrão ela é 100% seu valor.
Como funciona:
- GOGC baixo: 50% roda com mais frequência isso reduz o uso de memória mas consome mais cpu.
- GOGC Alto: 200% roda com menos frequência isso aumenta o uso de memória mas economiza cpu.
- GOGC off: Desativado
Como usar:
debug.SetGCPercent(200)
0 comentários