Created
October 9, 2017 15:09
-
-
Save cstockton/2c7e9346af7b7daad11bf9a754a3716e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BenchmarkSend/128-24 200000 5788 ns/op | |
BenchmarkSend/128#01-24 1000000 2053 ns/op | |
BenchmarkSend/256-24 100000 10465 ns/op | |
BenchmarkSend/256#01-24 500000 3311 ns/op | |
BenchmarkSend/512-24 100000 18025 ns/op | |
BenchmarkSend/512#01-24 200000 6123 ns/op | |
BenchmarkSend/1024-24 30000 36596 ns/op | |
BenchmarkSend/1024#01-24 100000 11584 ns/op | |
BenchmarkSend/2048-24 20000 64805 ns/op | |
BenchmarkSend/2048#01-24 50000 22978 ns/op | |
BenchmarkSend/4096-24 10000 140308 ns/op | |
BenchmarkSend/4096#01-24 30000 40229 ns/op | |
BenchmarkSend/8192-24 5000 284343 ns/op | |
BenchmarkSend/8192#01-24 20000 66941 ns/op | |
BenchmarkSend/16384-24 2000 527173 ns/op | |
BenchmarkSend/16384#01-24 10000 153594 ns/op |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//go:nosplit | |
func chansendn1(c *hchan, n int, elem unsafe.Pointer) { | |
chansendn(c, elem, n, true, getcallerpc(unsafe.Pointer(&c))) | |
} | |
func chansendn(c *hchan, ep unsafe.Pointer, n int, block bool, callerpc uintptr) bool { | |
if c == nil { | |
if !block { | |
return false | |
} | |
gopark(nil, nil, "chan send (nil chan)", traceEvGoStop, 2) | |
throw("unreachable") | |
} | |
if raceenabled { | |
racereadpc(unsafe.Pointer(c), callerpc, funcPC(chansend)) | |
} | |
if !block && c.closed == 0 && ((c.dataqsiz == 0 && c.recvq.first == nil) || | |
(c.dataqsiz > 0 && c.qcount == c.dataqsiz)) { | |
return false | |
} | |
lock(&c.lock) | |
if c.closed != 0 { | |
unlock(&c.lock) | |
panic(plainError("send on closed channel")) | |
} | |
for ; n > 0; n-- { | |
for sg := c.recvq.dequeue(); sg != nil; sg = c.recvq.dequeue() { | |
// Found a waiting receiver. We pass the value we want to send | |
// directly to the receiver, bypassing the channel buffer (if any). | |
send(c, sg, ep, func() { unlock(&c.lock) }, 3) | |
continue | |
} | |
if c.qcount < c.dataqsiz { | |
// Space is available in the channel buffer. Enqueue the element to send. | |
qp := chanbuf(c, c.sendx) | |
if raceenabled { | |
raceacquire(qp) | |
racerelease(qp) | |
} | |
typedmemmove(c.elemtype, qp, ep) | |
c.sendx++ | |
if c.sendx == c.dataqsiz { | |
c.sendx = 0 | |
} | |
c.qcount++ | |
continue | |
} | |
} | |
unlock(&c.lock) | |
return n == 0 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package chansendn | |
import ( | |
"unsafe" | |
) | |
//go:linkname chansend1 runtime.chansend1 | |
func chansend1(ch unsafe.Pointer, val unsafe.Pointer) bool | |
//go:linkname chansendn1 runtime.chansendn1 | |
func chansendn1(ch unsafe.Pointer, n int, elem unsafe.Pointer) uintptr | |
func sendLoop(ch chan struct{}, n int) { | |
if n > cap(ch) { | |
panic(`end-start > cap(ch)`) | |
} | |
for ; n > 0; n-- { | |
ch <- struct{}{} | |
} | |
} | |
func sendN(ch chan struct{}, n int) { | |
if n > cap(ch) { | |
panic(`end-start > cap(ch)`) | |
} | |
var val struct{} | |
chansendn1(chanOf(ch), n, unsafe.Pointer(&val)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package event | |
import ( | |
"fmt" | |
"testing" | |
) | |
func BenchmarkSend(b *testing.B) { | |
b.ReportAllocs() | |
b.ResetTimer() | |
for count := 128; count < 32768; count *= 2 { | |
b.Run(fmt.Sprint(count), func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
ch := make(chan struct{}, count) | |
sendLoop(ch, count) | |
} | |
}) | |
b.Run(fmt.Sprint(count), func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
ch := make(chan struct{}, count) | |
sendN(ch, count) | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment