Perfilando código Go: encontrando gargalos na prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que perfilamento de código Go é um must have

O desenvolvimento em Go (Golang) é conhecido por seu desempenho e eficiência. No entanto, até o código mais rápido pode ficar lento se não forem consideradas as particularidades do trabalho com memória, goroutines ou entrada/saída. Perfilamento é o processo de coleta de dados sobre a execução de um programa, que permite olhar "sob o capô" e entender quais funções consomem mais CPU, memória ou tempo.

Neste artigo, vamos explorar as ferramentas práticas de perfilamento em Go: pprof, trace e benchmarks integrados. Você aprenderá a encontrar gargalos e otimizar código com exemplos reais.



1. Principais ferramentas de perfilamento em Golang

O Go fornece um arsenal poderoso para perfilamento diretamente do pacote padrão. Vamos considerar três abordagens principais:

  • pprof — perfilamento de CPU, memória, bloqueios e goroutines.
  • trace — rastreamento de eventos: criação de goroutines, chamadas de sistema, GC.
  • benchmark — teste de desempenho integrado usando go test -bench.

Para começar com pprof, basta importar net/http/pprof no seu servidor HTTP ou usar runtime/pprof para aplicações CLI.



1.1. Como executar o perfilamento de CPU

A maneira mais simples é adicionar um endpoint ao seu servidor HTTP:

package main

import ( "log" "net/http" _ "net/http/pprof")

func main() { go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() // seu código principal select {}}

Após a execução, abra http://localhost:6060/debug/pprof/ — você verá um painel. Para coletar um perfil de CPU por 30 segundos, execute:

go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

Isso baixará os dados e abrirá o console interativo do pprof.



2. Encontrando gargalos com pprof: CPU e memória

Suponha que temos uma função que processa um grande array de dados. Suspeitamos que ela está lenta. Vamos escrever um exemplo de teste e perfilá-lo.



2.1. Exemplo de código lento

package main

import ( "fmt" "time")

func slowFunction(data []int) int { sum := 0 for _, v := range data { time.Sleep(1 * time.Microsecond) // simulação de trabalho sum += v * v } return sum}

func main() { data := make([]int, 100000) for i := range data { data[i] = i } result := slowFunction(data) fmt.Println(result)}

Vamos executar o perfilamento de CPU:

go run main.go &go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=10

No navegador, será aberta uma visualização — o grafo de chamadas (call graph). A espessura das arestas mostra quanto tempo cada função consumiu. Veremos imediatamente que slowFunction e time.Sleep são os principais consumidores de CPU.



2.2. Análise de memória (heap profile)

Para encontrar vazamentos de memória ou objetos que ocupam muito espaço, use:

go tool pprof http://localhost:6060/debug/pprof/heap

No console interativo, você pode executar o comando top:

(pprof) top10Showing nodes accounting for 80MB, 100% of 80MB total      flat  flat%   sum%        cum   cum%      40MB 50.00% 50.00%       40MB 50.00%  main.slowFunction      20MB 25.00% 75.00%       20MB 25.00%  main.createLargeSlice      20MB 25.00% 100.00%      20MB 25.00%  runtime.makeslice

Isso mostra quais funções estão alocando mais memória. Se você perceber que main.slowFunction está alocando 40MB, vale a pena considerar uma refatoração — por exemplo, usar reutilização de slices.

Blogs

Book Recommendations