1
0
mirror of https://github.com/golang/go synced 2024-11-13 18:10:24 -07:00

runtime: add more chan benchmarks

Add benchmarks for:
1. non-blocking failing receive (polling of "stop" chan)
2. channel-based semaphore (gate pattern)
3. select-based producer/consumer (pass data through a channel, but also wait on "stop" and "timeout" channels)

LGTM=r
R=golang-codereviews, r
CC=bradfitz, golang-codereviews, iant, khr
https://golang.org/cl/59040043
This commit is contained in:
Dmitriy Vyukov 2014-02-04 09:41:48 +04:00
parent 9ed5995cfe
commit 3baceaa151

View File

@ -430,6 +430,30 @@ func TestMultiConsumer(t *testing.T) {
} }
} }
func BenchmarkChanNonblocking(b *testing.B) {
const CallsPerSched = 1000
procs := runtime.GOMAXPROCS(-1)
N := int32(b.N / CallsPerSched)
c := make(chan bool, procs)
myc := make(chan int)
for p := 0; p < procs; p++ {
go func() {
for atomic.AddInt32(&N, -1) >= 0 {
for g := 0; g < CallsPerSched; g++ {
select {
case <-myc:
default:
}
}
}
c <- true
}()
}
for p := 0; p < procs; p++ {
<-c
}
}
func BenchmarkSelectUncontended(b *testing.B) { func BenchmarkSelectUncontended(b *testing.B) {
const CallsPerSched = 1000 const CallsPerSched = 1000
procs := runtime.GOMAXPROCS(-1) procs := runtime.GOMAXPROCS(-1)
@ -670,6 +694,66 @@ func BenchmarkChanProdConsWork100(b *testing.B) {
benchmarkChanProdCons(b, 100, 100) benchmarkChanProdCons(b, 100, 100)
} }
func BenchmarkSelectProdCons(b *testing.B) {
const CallsPerSched = 1000
procs := runtime.GOMAXPROCS(-1)
N := int32(b.N / CallsPerSched)
c := make(chan bool, 2*procs)
myc := make(chan int, 128)
myclose := make(chan bool)
for p := 0; p < procs; p++ {
go func() {
// Producer: sends to myc.
foo := 0
// Intended to not fire during benchmarking.
mytimer := time.After(time.Hour)
for atomic.AddInt32(&N, -1) >= 0 {
for g := 0; g < CallsPerSched; g++ {
// Model some local work.
for i := 0; i < 100; i++ {
foo *= 2
foo /= 2
}
select {
case myc <- 1:
case <-mytimer:
case <-myclose:
}
}
}
myc <- 0
c <- foo == 42
}()
go func() {
// Consumer: receives from myc.
foo := 0
// Intended to not fire during benchmarking.
mytimer := time.After(time.Hour)
loop:
for {
select {
case v := <-myc:
if v == 0 {
break loop
}
case <-mytimer:
case <-myclose:
}
// Model some local work.
for i := 0; i < 100; i++ {
foo *= 2
foo /= 2
}
}
c <- foo == 42
}()
}
for p := 0; p < procs; p++ {
<-c
<-c
}
}
func BenchmarkChanCreation(b *testing.B) { func BenchmarkChanCreation(b *testing.B) {
const CallsPerSched = 1000 const CallsPerSched = 1000
procs := runtime.GOMAXPROCS(-1) procs := runtime.GOMAXPROCS(-1)
@ -694,9 +778,23 @@ func BenchmarkChanCreation(b *testing.B) {
func BenchmarkChanSem(b *testing.B) { func BenchmarkChanSem(b *testing.B) {
type Empty struct{} type Empty struct{}
c := make(chan Empty, 1) const CallsPerSched = 1000
for i := 0; i < b.N; i++ { procs := runtime.GOMAXPROCS(0)
c <- Empty{} N := int32(b.N / CallsPerSched)
c := make(chan bool, procs)
myc := make(chan Empty, procs)
for p := 0; p < procs; p++ {
go func() {
for atomic.AddInt32(&N, -1) >= 0 {
for g := 0; g < CallsPerSched; g++ {
myc <- Empty{}
<-myc
}
}
c <- true
}()
}
for p := 0; p < procs; p++ {
<-c <-c
} }
} }