Performance

Otimização de Performance em Go: Técnicas Avançadas

2 min de leitura
Marco Ollivier
GoPerformanceOtimizaçãoProfiling

Performance é crucial em sistemas backend. Neste artigo, compartilho técnicas avançadas de otimização em Go que aprendi trabalhando em sistemas de alta escala.

Profiling: O Primeiro Passo

Antes de otimizar, você precisa medir. Go oferece excelentes ferramentas de profiling.

CPU Profiling

import _ "net/http/pprof"

func main() {
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()

    // Seu código aqui
}

Memory Profiling

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

Otimizações de Memória

Pool de Objetos

var bufferPool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 0, 1024)
    },
}

func processData(data []byte) {
    buf := bufferPool.Get().([]byte)
    defer bufferPool.Put(buf[:0])

    // Use buf para processamento
}

Evitar Alocações Desnecessárias

// ❌ Ruim - cria slice a cada chamada
func badExample(items []string) []string {
    result := []string{}
    for _, item := range items {
        if len(item) > 0 {
            result = append(result, item)
        }
    }
    return result
}

// ✅ Bom - pré-aloca slice
func goodExample(items []string) []string {
    result := make([]string, 0, len(items))
    for _, item := range items {
        if len(item) > 0 {
            result = append(result, item)
        }
    }
    return result
}

Otimizações de CPU

Uso Eficiente de Goroutines

// Worker pool pattern
func processWithWorkerPool(jobs <-chan Job, results chan<- Result) {
    const numWorkers = runtime.NumCPU()

    var wg sync.WaitGroup
    for i := 0; i < numWorkers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for job := range jobs {
                results <- processJob(job)
            }
        }()
    }

    go func() {
        wg.Wait()
        close(results)
    }()
}

Benchmarking

func BenchmarkStringConcatenation(b *testing.B) {
    for i := 0; i < b.N; i++ {
        var result string
        for j := 0; j < 100; j++ {
            result += "test"
        }
    }
}

func BenchmarkStringBuilder(b *testing.B) {
    for i := 0; i < b.N; i++ {
        var builder strings.Builder
        for j := 0; j < 100; j++ {
            builder.WriteString("test")
        }
        _ = builder.String()
    }
}

Conclusão

Performance em Go requer medição constante e otimizações pontuais. Use as ferramentas certas e sempre meça antes e depois das mudanças.