Skip to content

Commit 2dda92f

Browse files
committed
runtime: make slice growth formula a bit smoother
Instead of growing 2x for < 1024 elements and 1.25x for >= 1024 elements, use a somewhat smoother formula for the growth factor. Start reducing the growth factor after 256 elements, but slowly. starting cap growth factor 256 2.0 512 1.63 1024 1.44 2048 1.35 4096 1.30 (Note that the real growth factor, both before and now, is somewhat larger because we round up to the next size class.) This CL also makes the growth monotonic (larger initial capacities make larger final capacities, which was not true before). See discussion at https://groups.google.com/g/golang-nuts/c/UaVlMQ8Nz3o 256 was chosen as the threshold to roughly match the total number of reallocations when appending to eventually make a very large slice. (We allocate smaller when appending to capacities [256,1024] and larger with capacities [1024,...]). Change-Id: I876df09fdc9ae911bb94e41cb62675229cb10512 Reviewed-on: https://go-review.googlesource.com/c/go/+/347917 Trust: Keith Randall <khr@golang.org> Trust: Martin Möhrmann <martin@golang.org> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Martin Möhrmann <martin@golang.org>
1 parent 301f6c8 commit 2dda92f

File tree

2 files changed

+9
-4
lines changed

2 files changed

+9
-4
lines changed

src/reflect/value.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,11 +2487,12 @@ func grow(s Value, extra int) (Value, int, int) {
24872487
if m == 0 {
24882488
m = extra
24892489
} else {
2490+
const threshold = 256
24902491
for m < i1 {
2491-
if i0 < 1024 {
2492+
if i0 < threshold {
24922493
m += m
24932494
} else {
2494-
m += m / 4
2495+
m += (m + 3*threshold) / 4
24952496
}
24962497
}
24972498
}

src/runtime/slice.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,17 @@ func growslice(et *_type, old slice, cap int) slice {
185185
if cap > doublecap {
186186
newcap = cap
187187
} else {
188-
if old.cap < 1024 {
188+
const threshold = 256
189+
if old.cap < threshold {
189190
newcap = doublecap
190191
} else {
191192
// Check 0 < newcap to detect overflow
192193
// and prevent an infinite loop.
193194
for 0 < newcap && newcap < cap {
194-
newcap += newcap / 4
195+
// Transition from growing 2x for small slices
196+
// to growing 1.25x for large slices. This formula
197+
// gives a smooth-ish transition between the two.
198+
newcap += (newcap + 3*threshold) / 4
195199
}
196200
// Set newcap to the requested cap when
197201
// the newcap calculation overflowed.

0 commit comments

Comments
 (0)