]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use multiplication with overflow check for makechan
authorMartin Möhrmann <moehrmann@google.com>
Mon, 22 Oct 2018 18:40:03 +0000 (20:40 +0200)
committerMartin Möhrmann <martisch@uos.de>
Tue, 23 Oct 2018 16:42:58 +0000 (16:42 +0000)
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>
src/runtime/chan.go

index 5cf0b86f586140ab53e9ad592190b422db8c309e..8662f00e132890264f6bb94251b64c9337748309 100644 (file)
@@ -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)