---
title: "Go prepara runtime.freegc para reduzir pressão no GC"
url: "https://golang.com.br/novidades/go-1-27-runtime-freegc-gc-alocacoes/"
markdown_url: "https://golang.com.br/novidades/go-1-27-runtime-freegc-gc-alocacoes.MD"
description: "runtime.freegc é uma proposta do Go para reutilizar memória morta mais cedo e reduzir pressão no GC sem mudar APIs do usuário."
date: "2026-05-08"
author: "Go Brasil"
---

# Go prepara runtime.freegc para reduzir pressão no GC

runtime.freegc é uma proposta do Go para reutilizar memória morta mais cedo e reduzir pressão no GC sem mudar APIs do usuário.


TL;DR: uma nova proposta de design no repositório `golang/proposal` descreve `runtime.freegc`, um mecanismo interno para o compilador e o runtime devolverem memória comprovadamente morta ao alocador antes de uma rodada normal do GC chegar nela. Não é uma API para aplicações chamarem manualmente. A promessa é reduzir taxa efetiva de alocação, ciclos de garbage collection e custo de CPU em padrões comuns, como crescimento repetido de slices, `strings.Builder`, mapas e decodificação com muita memória temporária.

## O que a proposta muda

O documento [design/74299-runtime-freegc.md](https://raw.githubusercontent.com/golang/proposal/master/design/74299-runtime-freegc.md) parte de uma observação simples: o programa Go frequentemente deixa de usar uma área de memória bem antes de o coletor de lixo conseguir reaproveitá-la. Hoje, mesmo quando o compilador ou o runtime já conseguem entender que um backing array antigo não será mais usado, essa memória normalmente continua no heap até o GC avançar o suficiente.

A proposta adiciona uma primitiva interna, `runtime.freegc`, para marcar um objeto do heap como reutilizável quando for seguro provar que ele está logicamente morto. O ponto importante é o “provar”: o design não propõe um `free` manual no estilo C, nem transfere para o desenvolvedor a responsabilidade de liberar memória. A chamada seria emitida por código do compilador ou do runtime em situações em que não há aliases utilizáveis para o objeto.

Isso coloca a ideia no mesmo território de otimizações como escape analysis e stack allocation: o código Go continua idiomático, mas o compilador ganha mais uma forma de reduzir trabalho futuro do GC.

## Onde isso pode aparecer no código do dia a dia

Um dos casos mais concretos é crescimento de slices. Quando um `append` precisa criar um backing array maior, o array antigo fica morto se o compilador provar que nenhum outro slice ainda aponta para ele. A proposta descreve um caminho interno chamado `runtime.growsliceNoAlias`, parecido com o `growslice` atual, mas capaz de liberar o backing array antigo depois da cópia.

O código do usuário não mudaria:

```go
func collect(input []int) []int {
    var out []int
    for _, x := range input {
        out = append(out, transform(x))
    }
    return out
}
```

Se `out` for comprovadamente não-aliasado durante os crescimentos intermediários, o runtime pode reaproveitar os arrays antigos mais cedo. O slice final continua válido e pode escapar normalmente como retorno da função.

A proposta também fala de alocações com `make([]T, size)` em que o backing array é temporário, tem tamanho dinâmico e precisa ir para o heap. Para esses casos, o compilador poderia usar alocações “rastreadas”, com nomes internos como `runtime.makeslicetracked64` e `runtime.freegcTracked`, para liberar vários objetos ao fim de um escopo sem manter ponteiros artificialmente vivos.

## Por que isso importa para performance

A melhoria não é “pausar menos o GC” por decreto. Ela tenta reduzir a quantidade de memória que o GC precisa tratar como pressão real de alocação. Se objetos mortos voltam ao alocador antes, o programa pode fazer menos alocações novas, acionar menos ciclos de coleta e passar menos tempo com write barriers ativas.

O design cita experimentos interessantes. Em um teste manual com `strings.Builder`, ganhos apareceram principalmente quando o builder crescia várias vezes: casos com muitos writes ficaram substancialmente mais rápidos porque buffers intermediários puderam ser reaproveitados. O texto também menciona experimentos em `reflect` combinados com `json/v2`, com reduções relevantes de alocação em alguns benchmarks reais de unmarshal.

Esses números não devem ser lidos como promessa direta para qualquer serviço Go. Eles mostram onde a técnica tem potencial: código que cria estruturas temporárias grandes, cresce buffers repetidamente ou faz muito trabalho de serialização. Em APIs e workers que já são sensíveis a GC, reduzir a pressão de heap pode aparecer como menor CPU, menor latência de cauda ou simplesmente mais folga antes de precisar mexer em pooling manual.

## O que não muda para aplicações

O mais saudável, por enquanto, é tratar `runtime.freegc` como detalhe de implementação. Desenvolvedores não devem planejar código chamando essa função. O próprio design descreve restrições fortes: ponteiros precisam ser para objetos do heap, tamanhos e metadados importam, objetos pequenos ou grandes demais podem não ser tratados, e finalizers ou cleanups criados pelo usuário ainda exigem cuidado especial.

Também há um detalhe contraintuitivo: inserir uma chamada tarde demais pode piorar liveness, porque passar o ponteiro para `freegc` mantém esse ponteiro vivo até a chamada. É justamente por isso que a proposta depende de integração fina com o compilador, e não de uma API pública.

Para quem escreve Go em produção, a recomendação prática continua a mesma: prefira código claro, meça com benchmarks e perfis, e evite pools manuais antes de ter evidência. Se essa proposta avançar até um release, parte do ganho esperado virá de código comum ficando mais eficiente sem alterações na base.

## Como acompanhar

A proposta ainda é uma peça de design com implementação inicial e vários detalhes em evolução. O documento menciona uma pilha de CLs, trabalho de análise de aliases no compilador e limitações atuais, como casos de `make` dentro de loops não estruturados. Também há relação com outras frentes de runtime, como mapas liberando armazenamento morto durante crescimento e split, desde que não haja iteração retendo as tabelas antigas.

O sinal mais importante é a direção: o time de Go segue investindo em reduzir custo de memória sem exigir que o usuário abandone o modelo seguro da linguagem. Depois de melhorias recentes em diagnóstico, como o perfil proposto para [leak de goroutines](/novidades/go-1-27-goroutineleak-pprof/), `runtime.freegc` aponta para outra frente do mesmo tema: tornar o runtime mais capaz de entender o ciclo de vida real dos objetos.

## Saiba mais

- [Proposta: runtime.freegc](https://raw.githubusercontent.com/golang/proposal/master/design/74299-runtime-freegc.md)
- [Issue golang/go#74299](https://github.com/golang/go/issues/74299)
- [CL stack inicial citado no design](https://go.dev/cl/673695)
- [Go 1.27 deve ganhar perfil para leak de goroutines](/novidades/go-1-27-goroutineleak-pprof/)
