]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add more chan benchmarks
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 4 Feb 2014 05:41:48 +0000 (09:41 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 4 Feb 2014 05:41:48 +0000 (09:41 +0400)
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

src/pkg/runtime/chan_test.go

index a855edb47c6533fc6673aaefbbdcfd780dfcd3f0..3ee7fe465d18be627ddd00292468970e3069b4da 100644 (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) {
        const CallsPerSched = 1000
        procs := runtime.GOMAXPROCS(-1)
@@ -670,6 +694,66 @@ func BenchmarkChanProdConsWork100(b *testing.B) {
        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) {
        const CallsPerSched = 1000
        procs := runtime.GOMAXPROCS(-1)
@@ -694,9 +778,23 @@ func BenchmarkChanCreation(b *testing.B) {
 
 func BenchmarkChanSem(b *testing.B) {
        type Empty struct{}
-       c := make(chan Empty, 1)
-       for i := 0; i < b.N; i++ {
-               c <- Empty{}
+       const CallsPerSched = 1000
+       procs := runtime.GOMAXPROCS(0)
+       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
        }
 }