---
title: "**Go Acelera: Alocação na Stack para um Desempenho Imbatível**"
url: "https://golang.com.br/blog/go-acelera-alocacao-na-stack-para-um-desempenho-imbativel/"
markdown_url: "https://golang.com.br/blog/go-acelera-alocacao-na-stack-para-um-desempenho-imbativel.MD"
description: "O artigo do blog oficial do Go discute otimizações recentes no compilador Go para reduzir alocações na heap, substituindo-as por alocações na stack...."
date: "2026-02-27"
author: "Go Blog (Resumo)"
---

# **Go Acelera: Alocação na Stack para um Desempenho Imbatível**

O artigo do blog oficial do Go discute otimizações recentes no compilador Go para reduzir alocações na heap, substituindo-as por alocações na stack....


O artigo do blog oficial do Go discute otimizações recentes no compilador Go para reduzir alocações na heap, substituindo-as por alocações na stack. Alocações na stack são significativamente mais rápidas e não sobrecarregam o garbage collector, resultando em programas mais eficientes em termos de tempo de execução e uso de memória. O artigo explora diferentes cenários e as melhorias introduzidas em versões recentes do Go (1.25 e 1.26) para otimizar a alocação de slices.

## O Problema das Alocações na Heap

Alocar memória na heap é uma operação relativamente custosa. Cada alocação envolve a execução de um código considerável e impõe uma carga adicional ao garbage collector (GC). Mesmo com otimizações recentes no GC, como o Green Tea, o overhead ainda é significativo. Alocações na stack, por outro lado, são muito mais baratas (às vezes até "gratuitas"), não afetam o GC e permitem um reuso rápido da memória, o que é benéfico para o cache.

## Alocação na Stack de Slices com Tamanho Constante

Considere o seguinte exemplo de código que processa tarefas recebidas de um channel:

```go
func process(c chan task) {
    var tasks []task
    for t := range c {
        tasks = append(tasks, t)
    }
    processAll(tasks)
}
```

Nesse código, a cada iteração do loop, a função `append` adiciona uma nova tarefa ao slice `tasks`. Inicialmente, o slice não possui um backing store (a área de memória onde os elementos do slice são armazenados). Assim, a função `append` precisa alocar um. Como não sabe o tamanho final do slice, ela começa com um tamanho pequeno (1). Nas iterações seguintes, se o backing store estiver cheio, `append` aloca um novo com o dobro do tamanho anterior, descartando o antigo. Esse processo gera várias alocações na heap e lixo para o GC, especialmente no início, quando o slice é pequeno.

Uma otimização comum é pré-alocar o slice com um tamanho estimado:

```go
func process2(c chan task) {
    tasks := make([]task, 0, 10) // provavelmente no máximo 10 tarefas
    for t := range c {
        tasks = append(tasks, t)
    }
    processAll(tasks)
}
```

Essa abordagem reduz o número de alocações, mas o compilador Go pode ir além. Se o tamanho máximo do backing store for conhecido em tempo de compilação (neste caso, 10 vezes o tamanho de `task`), ele pode alocar o backing store na stack do frame da função `process2`, eliminando completamente a necessidade de alocação na heap. Essa otimização depende do backing store não "escapar" para a heap dentro de `processAll`.

## Alocação na Stack de Slices com Tamanho Variável

E se o tamanho do slice não for conhecido em tempo de compilação? Considere o seguinte:

```go
func process3(c chan task, lengthGuess int) {
    tasks := make([]task, 0, lengthGuess)
    for t := range c {
        tasks = append(tasks, t)
    }
    processAll(tasks)
}
```

Em versões anteriores ao Go 1.25, o tamanho variável do backing store impedia a alocação na stack. No entanto, o Go 1.25 introduziu uma otimização inteligente: para certas alocações de slice, o compilador aloca automaticamente um pequeno backing store (atualmente, 32 bytes) na stack. Se o tamanho solicitado para o slice for pequeno o suficiente para caber nesse backing store, ele é usado. Caso contrário, a alocação ocorre na heap como de costume.

Essa otimização permite que `process3` execute sem alocações na heap se `lengthGuess` for pequeno o suficiente e corresponder ao número real de elementos no channel `c`.

## Alocação na Stack de Slices Alocados por Append

O Go 1.26 vai ainda mais longe, permitindo a alocação na stack mesmo quando o tamanho do slice é desconhecido e o `append` é usado sem pré-alocação.

```go
func process(c chan task) {
    var tasks []task
    for t := range c {
        tasks = append(tasks, t)
    }
    processAll(tasks)
}
```

Nesse caso, o compilador aloca um pequeno backing store especulativo na stack. Na primeira iteração do loop, `append` usa esse backing store. Se o backing store da stack for grande o suficiente para acomodar os elementos adicionados, as primeiras iterações não exigirão alocações na heap. Quando o backing store da stack estiver cheio, `append` alocará um novo na heap, mas as alocações iniciais na heap (de tamanhos 1, 2, 4, etc.) são evitadas, reduzindo o overhead e o lixo para o GC.

## Slices que "Escapam"

Se um slice "escapar" da função (por exemplo, sendo retornado), seu backing store não pode ser alocado na stack, pois o frame da stack da função desaparece quando ela retorna.

```go
func extract(c chan task) []task {
    var tasks []task
    for t := range c {
        tasks = append(tasks, t)
    }
    return tasks
}
```

Nesse caso, o backing store do slice retornado por `extract` deve ser alocado na heap. No entanto, o compilador ainda pode otimizar a alocação dos slices intermediários usados dentro do loop, alocando-os na stack. Uma abordagem comum é criar uma copia do slice dentro da função:

```go
func extract2(c chan task) []task {
    var tasks []task
    for t := range c {
        tasks = append(tasks, t)
    }
    tasks2 := make([]task, len(tasks))
    copy(tasks2, tasks)
    return tasks2
}
```

## Implicações Práticas

As otimizações de alocação na stack introduzidas nas versões recentes do Go têm um impacto significativo no desempenho e na eficiência de memória dos programas Go. Ao reduzir o número de alocações na heap e a carga sobre o garbage collector, essas otimizações resultam em programas mais rápidos e com menor consumo de memória.

Os desenvolvedores podem se beneficiar dessas otimizações simplesmente atualizando para as versões mais recentes do Go. Em muitos casos, nenhuma alteração no código é necessária para aproveitar as melhorias. Em outros casos, pequenas modificações, como pré-alocar slices com um tamanho estimado, podem aumentar ainda mais o desempenho.

As otimizações de alocação na stack são um exemplo do compromisso contínuo da equipe Go em melhorar o desempenho da linguagem e fornecer aos desenvolvedores ferramentas para escrever programas eficientes e escaláveis.

---

## Artigo Original

Este e um resumo em português do artigo original publicado no blog oficial do Go.

**Titulo original:** Allocating on the Stack

[Leia o artigo completo em ingles no Go Blog](https://go.dev/blog/allocation-optimizations)

*Autor original: Keith Randall*
