snapshot of https://github.com/uber-go/guide.git (master, 2026-09-15; blobs > 131072B omitted)
This commit is contained in:
119
src/container-capacity.md
Normal file
119
src/container-capacity.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Prefer Specifying Container Capacity
|
||||
|
||||
Specify container capacity where possible in order to allocate memory for the
|
||||
container up front. This minimizes subsequent allocations (by copying and
|
||||
resizing of the container) as elements are added.
|
||||
|
||||
## Specifying Map Capacity Hints
|
||||
|
||||
Where possible, provide capacity hints when initializing
|
||||
maps with `make()`.
|
||||
|
||||
```go
|
||||
make(map[T1]T2, hint)
|
||||
```
|
||||
|
||||
Providing a capacity hint to `make()` tries to right-size the
|
||||
map at initialization time, which reduces the need for growing
|
||||
the map and allocations as elements are added to the map.
|
||||
|
||||
Note that, unlike slices, map capacity hints do not guarantee complete,
|
||||
preemptive allocation, but are used to approximate the number of hashmap buckets
|
||||
required. Consequently, allocations may still occur when adding elements to the
|
||||
map, even up to the specified capacity.
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Bad</th><th>Good</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>
|
||||
|
||||
```go
|
||||
files, _ := os.ReadDir("./files")
|
||||
|
||||
m := make(map[string]os.DirEntry)
|
||||
for _, f := range files {
|
||||
m[f.Name()] = f
|
||||
}
|
||||
```
|
||||
|
||||
</td><td>
|
||||
|
||||
```go
|
||||
|
||||
files, _ := os.ReadDir("./files")
|
||||
|
||||
m := make(map[string]os.DirEntry, len(files))
|
||||
for _, f := range files {
|
||||
m[f.Name()] = f
|
||||
}
|
||||
```
|
||||
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
|
||||
`m` is created without a size hint; the map will resize
|
||||
dynamically, causing multiple allocations as it grows.
|
||||
|
||||
</td><td>
|
||||
|
||||
`m` is created with a size hint; there may be fewer
|
||||
allocations at assignment time.
|
||||
|
||||
</td></tr>
|
||||
</tbody></table>
|
||||
|
||||
## Specifying Slice Capacity
|
||||
|
||||
Where possible, provide capacity hints when initializing slices with `make()`,
|
||||
particularly when appending.
|
||||
|
||||
```go
|
||||
make([]T, length, capacity)
|
||||
```
|
||||
|
||||
Unlike maps, slice capacity is not a hint: the compiler will allocate enough
|
||||
memory for the capacity of the slice as provided to `make()`, which means that
|
||||
subsequent `append()` operations will incur zero allocations (until the length
|
||||
of the slice matches the capacity, after which any appends will require a resize
|
||||
to hold additional elements).
|
||||
|
||||
<table>
|
||||
<thead><tr><th>Bad</th><th>Good</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>
|
||||
|
||||
```go
|
||||
for n := 0; n < b.N; n++ {
|
||||
data := make([]int, 0)
|
||||
for k := 0; k < size; k++{
|
||||
data = append(data, k)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</td><td>
|
||||
|
||||
```go
|
||||
for n := 0; n < b.N; n++ {
|
||||
data := make([]int, 0, size)
|
||||
for k := 0; k < size; k++{
|
||||
data = append(data, k)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
|
||||
```plain
|
||||
BenchmarkBad-4 100000000 2.48s
|
||||
```
|
||||
|
||||
</td><td>
|
||||
|
||||
```plain
|
||||
BenchmarkGood-4 100000000 0.21s
|
||||
```
|
||||
|
||||
</td></tr>
|
||||
</tbody></table>
|
||||
Reference in New Issue
Block a user