← Back to Cecep Azhar
Cecep Azhar #golang#performance#optimization#profiling#memory#benchmark

Teknik Optimasi Performance Golang untuk Production

Cecep Saeful Azhar • 16 Oct 2026
Teknik Optimasi Performance Golang untuk Production
Tips optimasi performance Go dari profiling, memory management, sampai algorithm optimization. Dari pengalaman handle high-traffic systems.

Ketika Go Terasa Lambat

Go dikenal cepat, tapi "cepat" bukan berarti tidak bisa dioptimasi. Saya pernah handle sistem yang memproses 50,000 request per detik, dan setiap millisecond latency yang bisa dikurangi berarti ribuan user yang lebih puas. Optimasi performance itu tentang data, bukan intuisi. Jangan menebak — profil dulu.

1. Profiling: Kenali Bottleneck-nya

Go punya built-in profiling tools yang excellent. Ini langkah pertama yang selalu saya lakukan:

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

func init() {
    go func() {
        http.ListenAndServe("localhost:6060", nil)
    }()
}

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

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

// Visualize:
// go tool pprof -http=:8080 profile.pb.gz

2. Memory Optimization

Dari profiling, saya menemukan bahwa sebagian besar memory issue di Go berkaitan dengan allocation yang tidak perlu:

// Bad: Creates new slice on every iteration
func processBad(items []string) []string {
    var result []string
    for _, item := range items {
        result = append(result, strings.ToUpper(item))
    }
    return result
}

// Good: Pre-allocate with known capacity
func processGood(items []string) []string {
    result := make([]string, 0, len(items))
    for _, item := range items {
        result = append(result, strings.ToUpper(item))
    }
    return result
}

// Better: Reuse buffer with sync.Pool
var bufferPool = sync.Pool{
    New: func() interface{} {
        return new(bytes.Buffer)
    },
}

func processBest(items []string) []string {
    buf := bufferPool.Get().(*bytes.Buffer)
    defer bufferPool.Put(buf)
    result := make([]string, 0, len(items))
    for _, item := range items {
        buf.Reset()
        buf.WriteString(strings.ToUpper(item))
        result = append(result, buf.String())
    }
    return result
}

3. Benchmarking

Go punya testing framework yang mendukung benchmarking secara native:

func BenchmarkProcess(b *testing.B) {
    items := generateTestData(1000)
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        process(items)
    }
}

func BenchmarkProcessParallel(b *testing.B) {
    items := generateTestData(1000)
    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            process(items)
        }
    })
}

// go test -bench=. -benchmem -count=5

4. Database Query Optimization

Dari pengalaman saya, 80% performance issue di Go applications itu sebenarnya di database layer. Beberapa tips:

5. Goroutine Management

Goroutine yang tidak dikontrol bisa menyebabkan memory leak. Saya selalu pakai pattern berikut:

func boundedWorkerPool(ctx context.Context, jobs <-chan Job, maxWorkers int) {
    sem := make(chan struct{}, maxWorkers)
    for job := range jobs {
        select {
        case <-ctx.Done():
            return
        case sem <- struct{}{}:
            go func(j Job) {
                defer func() { <-sem }()
                process(j)
            }(job)
        }
    }
}

Kesimpulan

Performance optimization di Go itu sistematis: profil, identifikasi bottleneck, optimasi, benchmark untuk verifikasi. Jangan pernah optimasi tanpa data. Dan ingat: premature optimization is the root of all evil — tapi juga, delayed optimization di production juga bisa jadi masalah besar.

← More articles from Cecep Azhar Central Content Hub Home →