From: Keith Randall Date: Tue, 7 Sep 2021 16:44:29 +0000 (-0700) Subject: runtime: make slice growth formula a bit smoother X-Git-Tag: go1.18beta1~1169 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2dda92ff6f9f07eeb110ecbf0fc2d7a0ddd27f9d;p=gostls13.git 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 Trust: Martin Möhrmann Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Martin Möhrmann --- diff --git a/src/reflect/value.go b/src/reflect/value.go index 33b81d7209..786c494166 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -2487,11 +2487,12 @@ func grow(s Value, extra int) (Value, int, int) { if m == 0 { m = extra } else { + const threshold = 256 for m < i1 { - if i0 < 1024 { + if i0 < threshold { m += m } else { - m += m / 4 + m += (m + 3*threshold) / 4 } } } diff --git a/src/runtime/slice.go b/src/runtime/slice.go index e8267be885..cfa862e047 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -185,13 +185,17 @@ func growslice(et *_type, old slice, cap int) slice { if cap > doublecap { newcap = cap } else { - if old.cap < 1024 { + const threshold = 256 + if old.cap < threshold { newcap = doublecap } else { // Check 0 < newcap to detect overflow // and prevent an infinite loop. for 0 < newcap && newcap < cap { - newcap += newcap / 4 + // Transition from growing 2x for small slices + // to growing 1.25x for large slices. This formula + // gives a smooth-ish transition between the two. + newcap += (newcap + 3*threshold) / 4 } // Set newcap to the requested cap when // the newcap calculation overflowed.