]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: optimize growslice
authorEgon Elbre <egonelbre@gmail.com>
Tue, 9 May 2023 08:29:51 +0000 (11:29 +0300)
committerGopher Robot <gobot@golang.org>
Mon, 4 Sep 2023 17:50:46 +0000 (17:50 +0000)
This is tiny optimization for growslice, which is probably too small to
measure easily.

Move the for loop to avoid multiple checks inside the loop.
Also, use >> 2 instead of /4, which generates fewer instructions.

Change-Id: I9ab09bdccb56f98ab22073f23d9e102c252238c7
Reviewed-on: https://go-review.googlesource.com/c/go/+/493795
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Egon Elbre <egonelbre@gmail.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
src/runtime/slice.go

index 228697a708134d13d3d30660630c9fb96b73ac8e..29e2fd5cbd5c436bd7a32b180ee01af7db56ed6a 100644 (file)
@@ -186,14 +186,21 @@ func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) slice
                if oldCap < threshold {
                        newcap = doublecap
                } else {
-                       // Check 0 < newcap to detect overflow
-                       // and prevent an infinite loop.
-                       for 0 < newcap && newcap < newLen {
+                       for {
                                // 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
+                               newcap += (newcap + 3*threshold) >> 2
+
+                               // We need to check `newcap >= newLen` and whether `newcap` overflowed.
+                               // newLen is guaranteed to be larger than zero, hence
+                               // when newcap overflows then `uint(newcap) > uint(newLen)`.
+                               // This allows to check for both with the same comparison.
+                               if uint(newcap) >= uint(newLen) {
+                                       break
+                               }
                        }
+
                        // Set newcap to the requested cap when
                        // the newcap calculation overflowed.
                        if newcap <= 0 {