aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorMartin Möhrmann <moehrmann@google.com>2018-10-22 20:40:03 +0200
committerMartin Möhrmann <martisch@uos.de>2018-10-23 16:42:58 +0000
commit286c7ae10c71a8faeba22e29928afe7fce7e2750 (patch)
tree2494f5b4c355ce97a804e8e2123501410b090312 /src/runtime
parent72f099c36bf2599ce73d054d463fc2950cfdcb05 (diff)
downloadgo-286c7ae10c71a8faeba22e29928afe7fce7e2750.tar.xz
runtime: use multiplication with overflow check for makechan
This improves performance for channels with an element size larger than 32 bytes and removes loading a value from the maxElems array for smaller element sizes. MakeChan/Byte 88.8ns ± 6% 85.2ns ± 1% -4.03% (p=0.000 n=10+10) MakeChan/Int 100ns ± 4% 96ns ± 2% -3.72% (p=0.000 n=9+10) MakeChan/Ptr 124ns ± 3% 126ns ± 2% ~ (p=0.068 n=10+10) MakeChan/Struct/0 80.5ns ± 2% 80.7ns ± 2% ~ (p=0.697 n=10+10) MakeChan/Struct/32 143ns ± 4% 141ns ± 2% ~ (p=0.221 n=10+10) MakeChan/Struct/40 169ns ± 2% 159ns ± 4% -6.26% (p=0.000 n=10+10) Updates #21588 Change-Id: Ifbf12a5af2f0ec7e1d2241ecfffab020e9abec48 Reviewed-on: https://go-review.googlesource.com/c/144017 Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/chan.go10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index 5cf0b86f58..8662f00e13 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -19,6 +19,7 @@ package runtime
import (
"runtime/internal/atomic"
+ "runtime/internal/math"
"unsafe"
)
@@ -78,7 +79,8 @@ func makechan(t *chantype, size int) *hchan {
throw("makechan: bad alignment")
}
- if size < 0 || uintptr(size) > maxSliceCap(elem.size) || uintptr(size)*elem.size > maxAlloc-hchanSize {
+ mem, overflow := math.MulUintptr(elem.size, uintptr(size))
+ if overflow || mem > maxAlloc-hchanSize || size < 0 {
panic(plainError("makechan: size out of range"))
}
@@ -88,7 +90,7 @@ func makechan(t *chantype, size int) *hchan {
// TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
var c *hchan
switch {
- case size == 0 || elem.size == 0:
+ case mem == 0:
// Queue or element size is zero.
c = (*hchan)(mallocgc(hchanSize, nil, true))
// Race detector uses this location for synchronization.
@@ -96,12 +98,12 @@ func makechan(t *chantype, size int) *hchan {
case elem.kind&kindNoPointers != 0:
// Elements do not contain pointers.
// Allocate hchan and buf in one call.
- c = (*hchan)(mallocgc(hchanSize+uintptr(size)*elem.size, nil, true))
+ c = (*hchan)(mallocgc(hchanSize+mem, nil, true))
c.buf = add(unsafe.Pointer(c), hchanSize)
default:
// Elements contain pointers.
c = new(hchan)
- c.buf = mallocgc(uintptr(size)*elem.size, elem, true)
+ c.buf = mallocgc(mem, elem, true)
}
c.elemsize = uint16(elem.size)