Rafael

Engenheiro de Software

Olá, Eu sou Rafael. Estou construindo coisas para a web e mobile.

Um desenvolvedor dedicado a criar experiências digitais de alto desempenho, acessíveis e limpas. Eu me especializo em transformar problemas complexos em soluções de engenharia elegantes.

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.

GO
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 global
  • Local é 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

GO
func main() {
    user := &User{Name: "Rafael"}
    user = nil
}

outro exemplo de vários. Quando a função termina, as referências locais desaparecem.

GO
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:

GO
debug.SetGCPercent(200)

0 comentários

Deixe seu comentário