From 3baceaa1519baada9f040c14b7f36e89a6c83144 Mon Sep 17 00:00:00 2001 From: Dmitriy Vyukov Date: Tue, 4 Feb 2014 09:41:48 +0400 Subject: [PATCH] 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 --- src/pkg/runtime/chan_test.go | 104 ++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 3 deletions(-) diff --git a/src/pkg/runtime/chan_test.go b/src/pkg/runtime/chan_test.go index a855edb47c..3ee7fe465d 100644 --- a/src/pkg/runtime/chan_test.go +++ b/src/pkg/runtime/chan_test.go @@ -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 } } -- 2.48.1