Golang / GoLang System Architecture and Testing Interview Questions
How do you find and fix memory allocation hotspots in a Go service using profiling?
Memory allocation hotspots cause GC pressure, latency spikes, and higher CPU usage. The workflow: benchmark to detect allocations, profile to find the source, fix (pre-allocate, use sync.Pool, reduce interface boxing), benchmark again to verify improvement.
// Step 1: identify hotspots with -benchmem // go test -bench=BenchmarkProcessRequests -benchmem -memprofile=mem.out // go tool pprof mem.out // > top10 -cum // > list processRequest // Step 2: fix common allocation patterns // PATTERN 1: pre-allocate slices to known capacity // Allocates N times as the slice grows: func collectIDs(users []User) []int { var ids []int for _, u := range users { ids = append(ids, u.ID) } return ids } // Zero allocations: func collectIDsFast(users []User) []int { ids := make([]int, 0, len(users)) // pre-allocate exact capacity for _, u := range users { ids = append(ids, u.ID) } return ids } // PATTERN 2: sync.Pool for frequently allocated/freed objects var bufPool = sync.Pool{ New: func() any { return &bytes.Buffer{} }, } func encodeResponse(v any) ([]byte, error) { buf := bufPool.Get().(*bytes.Buffer) buf.Reset() defer bufPool.Put(buf) if err := json.NewEncoder(buf).Encode(v); err != nil { return nil, err } return buf.Bytes(), nil } // PATTERN 3: avoid interface boxing of small values // This allocates (int escapes to heap when stored as interface): func logValue(v interface{}) { fmt.Println(v) } logValue(42) // 42 allocated on heap // Use type-specific overloads or generics instead func logInt(v int) { fmt.Println(v) } // no allocation // PATTERN 4: strings.Builder instead of string concatenation // Step 3: verify with benchmark comparison // go test -bench=BenchmarkCollectIDs -benchmem -count=5 > after.txt // benchstat before.txt after.txt
More Related questions...