]> Cypherpunks.ru repositories - gostls13.git/commitdiff
slices: amortize allocations in Insert
authorIan Lance Taylor <iant@golang.org>
Wed, 12 Apr 2023 20:57:21 +0000 (13:57 -0700)
committerGopher Robot <gobot@golang.org>
Thu, 13 Apr 2023 17:55:12 +0000 (17:55 +0000)
Fixes #54948

Change-Id: I467afb940b539b100dcce687b05914a9da7b9ed2
Reviewed-on: https://go-review.googlesource.com/c/go/+/484159
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Valentin Deleplace <deleplace@google.com>
src/slices/slices.go
src/slices/slices_test.go

index ea1dea573c9111af760a0c0e2c9305c7430be875..4a35ec5c23f86eb1429499c9ca1add47c6328c67 100644 (file)
@@ -88,7 +88,11 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
                copy(s2[i:], v)
                return s2
        }
-       s2 := make(S, tot)
+       // Use append rather than make so that we bump the size of
+       // the slice up to the next storage class.
+       // This is what Grow does but we don't call Grow because
+       // that might copy the values twice.
+       s2 := append(S(nil), make(S, tot)...)
        copy(s2, s[:i])
        copy(s2[i:], v)
        copy(s2[i+len(v):], s[i:])
index 720e731ddf2b5fe6ac349ac2554e4dafa7ec43b6..0f3df43e06150abc84e269792bfeb55a0530b007 100644 (file)
@@ -256,6 +256,20 @@ func TestInsert(t *testing.T) {
                        t.Errorf("Insert(%v, %d, %v...) = %v, want %v", test.s, test.i, test.add, got, test.want)
                }
        }
+
+       if !testenv.OptimizationOff() && !race.Enabled {
+               // Allocations should be amortized.
+               const count = 50
+               n := testing.AllocsPerRun(10, func() {
+                       s := []int{1, 2, 3}
+                       for i := 0; i < count; i++ {
+                               s = Insert(s, 0, 1)
+                       }
+               })
+               if n > count/2 {
+                       t.Errorf("too many allocations inserting %d elements: got %v, want less than %d", count, n, count/2)
+               }
+       }
 }
 
 var deleteTests = []struct {