Skip to content

Commit 286c7ae

Browse files
committed
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 <[email protected]>
1 parent 72f099c commit 286c7ae

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

src/runtime/chan.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package runtime
1919

2020
import (
2121
"runtime/internal/atomic"
22+
"runtime/internal/math"
2223
"unsafe"
2324
)
2425

@@ -78,7 +79,8 @@ func makechan(t *chantype, size int) *hchan {
7879
throw("makechan: bad alignment")
7980
}
8081

81-
if size < 0 || uintptr(size) > maxSliceCap(elem.size) || uintptr(size)*elem.size > maxAlloc-hchanSize {
82+
mem, overflow := math.MulUintptr(elem.size, uintptr(size))
83+
if overflow || mem > maxAlloc-hchanSize || size < 0 {
8284
panic(plainError("makechan: size out of range"))
8385
}
8486

@@ -88,20 +90,20 @@ func makechan(t *chantype, size int) *hchan {
8890
// TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
8991
var c *hchan
9092
switch {
91-
case size == 0 || elem.size == 0:
93+
case mem == 0:
9294
// Queue or element size is zero.
9395
c = (*hchan)(mallocgc(hchanSize, nil, true))
9496
// Race detector uses this location for synchronization.
9597
c.buf = c.raceaddr()
9698
case elem.kind&kindNoPointers != 0:
9799
// Elements do not contain pointers.
98100
// Allocate hchan and buf in one call.
99-
c = (*hchan)(mallocgc(hchanSize+uintptr(size)*elem.size, nil, true))
101+
c = (*hchan)(mallocgc(hchanSize+mem, nil, true))
100102
c.buf = add(unsafe.Pointer(c), hchanSize)
101103
default:
102104
// Elements contain pointers.
103105
c = new(hchan)
104-
c.buf = mallocgc(uintptr(size)*elem.size, elem, true)
106+
c.buf = mallocgc(mem, elem, true)
105107
}
106108

107109
c.elemsize = uint16(elem.size)

0 commit comments

Comments
 (0)