diff options
| author | Martin Möhrmann <moehrmann@google.com> | 2018-04-26 18:30:11 +0200 |
|---|---|---|
| committer | Martin Möhrmann <moehrmann@google.com> | 2018-05-06 04:28:23 +0000 |
| commit | a8a60ac2a7bec701de6b502889e1dc740761e183 (patch) | |
| tree | c53e32a00f0fc81f45099b0eadca4cfd6846ee24 /src/runtime/slice.go | |
| parent | 87412a143051d63f4ce68900f4668b2a3fb5c4f2 (diff) | |
| download | go-a8a60ac2a7bec701de6b502889e1dc740761e183.tar.xz | |
cmd/compile: optimize append(x, make([]T, y)...) slice extension
Changes the compiler to recognize the slice extension pattern
append(x, make([]T, y)...)
and replace it with growslice and an optional memclr to avoid an allocation for make([]T, y).
Memclr is not called in case growslice already allocated a new cleared backing array
when T contains pointers.
amd64:
name old time/op new time/op delta
ExtendSlice/IntSlice 103ns ± 4% 57ns ± 4% -44.55% (p=0.000 n=18+18)
ExtendSlice/PointerSlice 155ns ± 3% 77ns ± 3% -49.93% (p=0.000 n=20+20)
ExtendSlice/NoGrow 50.2ns ± 3% 5.2ns ± 2% -89.67% (p=0.000 n=18+18)
name old alloc/op new alloc/op delta
ExtendSlice/IntSlice 64.0B ± 0% 32.0B ± 0% -50.00% (p=0.000 n=20+20)
ExtendSlice/PointerSlice 64.0B ± 0% 32.0B ± 0% -50.00% (p=0.000 n=20+20)
ExtendSlice/NoGrow 32.0B ± 0% 0.0B -100.00% (p=0.000 n=20+20)
name old allocs/op new allocs/op delta
ExtendSlice/IntSlice 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=20+20)
ExtendSlice/PointerSlice 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=20+20)
ExtendSlice/NoGrow 1.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20)
Fixes #21266
Change-Id: Idc3077665f63cbe89762b590c5967a864fd1c07f
Reviewed-on: https://go-review.googlesource.com/109517
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Diffstat (limited to 'src/runtime/slice.go')
| -rw-r--r-- | src/runtime/slice.go | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/src/runtime/slice.go b/src/runtime/slice.go index 40c5995153..fd5d08b52c 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -44,6 +44,14 @@ func maxSliceCap(elemsize uintptr) uintptr { return maxAlloc / elemsize } +func panicmakeslicelen() { + panic(errorString("makeslice: len out of range")) +} + +func panicmakeslicecap() { + panic(errorString("makeslice: cap out of range")) +} + func makeslice(et *_type, len, cap int) slice { // NOTE: The len > maxElements check here is not strictly necessary, // but it produces a 'len out of range' error instead of a 'cap out of range' error @@ -52,11 +60,11 @@ func makeslice(et *_type, len, cap int) slice { // See issue 4085. maxElements := maxSliceCap(et.size) if len < 0 || uintptr(len) > maxElements { - panic(errorString("makeslice: len out of range")) + panicmakeslicelen() } if cap < len || uintptr(cap) > maxElements { - panic(errorString("makeslice: cap out of range")) + panicmakeslicecap() } p := mallocgc(et.size*uintptr(cap), et, true) @@ -66,12 +74,12 @@ func makeslice(et *_type, len, cap int) slice { func makeslice64(et *_type, len64, cap64 int64) slice { len := int(len64) if int64(len) != len64 { - panic(errorString("makeslice: len out of range")) + panicmakeslicelen() } cap := int(cap64) if int64(cap) != cap64 { - panic(errorString("makeslice: cap out of range")) + panicmakeslicecap() } return makeslice(et, len, cap) |
