Boost Go Performance with slices.Grow: Pre‑allocate to Avoid Repeated Expansions

Using Go 1.21’s experimental slices.Grow function to pre‑allocate slice capacity can dramatically reduce allocation overhead and latency, as demonstrated by a real‑world log‑aggregation service where response time dropped from 80 ms to 25 ms and memory allocations fell by 70 %.

Golang Shines
Golang Shines
Golang Shines
Boost Go Performance with slices.Grow: Pre‑allocate to Avoid Repeated Expansions

Slice growth overhead

When append exceeds a slice's capacity, Go allocates a larger array, copies the existing elements, and frees the old array. Each growth incurs a memory allocation and a copy, which can dominate CPU time in high‑frequency paths.

var data []int
for i := 0; i < 1000000; i++ {
    data = append(data, i) // many reallocations
}

In a log‑aggregation service memory allocation accounted for about 40 % of CPU time, leading to a panic runtime error: slice bounds out of range.

Go 1.21 experimental slices.Grow

slices.Grow

reserves capacity before appending.

import "slices"

s := []int{1, 2, 3}
s = slices.Grow(s, 5) // reserve space for 5 more elements
s = append(s, 4, 5, 6, 7, 8) // no extra allocation

Grow only changes capacity, not length. After the call len(s) is unchanged while cap(s) may increase.

If the existing capacity is sufficient, Grow returns the original slice unchanged.

When capacity is insufficient, a new underlying array is allocated. The address of &s[0] changes, which can be observed with fmt.Printf("%p", &s[0]).

Real‑world case

Function aggregateEvents reads thousands of rows and appends each event to a slice.

func aggregateEvents(userID string) []Event {
    var events []Event
    rows := db.Query("SELECT ... WHERE user_id = ?", userID)
    for rows.Next() {
        var e Event
        rows.Scan(&e)
        events = append(events, e) // each append may trigger growth
    }
    return events
}

When the number of events exceeded roughly 500, latency spiked and runtime.growslice dominated CPU usage in pprof.

Optimization with pre‑allocation

estimated := estimateEventCount(userID)

events := make([]Event, 0, 0)
events = slices.Grow(events, estimated) // pre‑reserve capacity

for rows.Next() {
    var e Event
    rows.Scan(&e)
    events = append(events, e) // now almost zero extra allocations
}

After applying the pre‑allocation, the 99th‑percentile latency dropped from ~80 ms to ~25 ms and memory allocations decreased by roughly 70 %.

Micro‑benchmark

Ordinary append : ~120 ms, ~20 allocations.

slices.Grow pre‑allocation : ~45 ms, 1 allocation.

Numbers are from a local benchmark; actual results depend on hardware and Go version.

Guidelines

Do not use when the final size is uncertain. Over‑estimating wastes memory.

Small slices (≈ < 100 elements) rarely benefit. The overhead of calling Grow can outweigh the cost of a few reallocations.

Frequent Grow followed by large slice release may fragment the heap. Consider pairing with sync.Pool in long‑running services.

When to apply

Only when an approximate element count greater than 100 is known and the code runs in a high‑frequency path.

Key takeaways

Understanding slice growth mechanics enables targeted performance improvements.

Pre‑allocating capacity with slices.Grow can dramatically reduce latency and allocation overhead.

The simplest change—calling a single library function—often yields the biggest gain.

Source: Huawei Cloud Community, golang学习记, https://bbs.huaweicloud.com/blogs/477729

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Performance Optimizationgobenchmarkmemory allocationslices.Grow
Golang Shines
Written by

Golang Shines

We share daily the latest Golang technical articles, practical resources, language news, tutorials, and real-world projects to help everyone learn and improve.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.