Skip to content

Commit 38095eb

Browse files
committed
runtime: Grow small slices more aggressively, larger more mildly
Align the capacity on the next power of two for small slices, but tries a milder (1.5x) over-allocation for slices with capacity over the threshold. This behavior is similar to (but not the same as) Big Go. Signed-off-by: L. Pereira <[email protected]>
1 parent f7d88e7 commit 38095eb

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

src/runtime/slice.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"unsafe"
88
)
99

10+
const DoubleCapThreshold = 64
11+
1012
// Builtin append(src, elements...) function: append elements to src and return
1113
// the modified (possibly expanded) slice.
1214
func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) {
@@ -41,10 +43,13 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr)
4143
return oldBuf, oldLen, oldCap
4244
}
4345

44-
// This can be made more memory-efficient by multiplying by some other constant, such as 1.5,
45-
// which seems to be allowed by the Go language specification (but this can be observed by
46-
// programs).
47-
newCap = 1 << bits.Len32(uint32(newCap))
46+
// Align the capacity on the next power of two for small slices, but tries a
47+
// milder (1.5x) over-allocation for slices with capacity over the threshold.
48+
if newCap < DoubleCapThreshold {
49+
newCap = 1 << bits.Len(uint(newCap))
50+
} else {
51+
newCap = (newCap / 2) * 3
52+
}
4853

4954
buf := alloc(newCap*elemSize, nil)
5055
if oldLen > 0 {

0 commit comments

Comments
 (0)