diff options
-rw-r--r-- | bench_test.go | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/bench_test.go b/bench_test.go index 82aaba1..08faa96 100644 --- a/bench_test.go +++ b/bench_test.go @@ -149,3 +149,89 @@ func BenchmarkPingPong(b *testing.B) { b.ReportAllocs() parallelPingPongs(b, 1) } + +const maxTokens = 25 + +func BenchmarkThunderingHerdCondVar(b *testing.B) { + for i := 0; i < b.N; i++ { + var mu sync.Mutex + consumer := sync.NewCond(&mu) + generator := sync.NewCond(&mu) + done := false + tokens := 0 + var pending sync.WaitGroup + for range iter.N(1000) { + pending.Add(1) + go func() { + mu.Lock() + for { + if tokens > 0 { + tokens-- + generator.Signal() + break + } + consumer.Wait() + } + mu.Unlock() + pending.Done() + }() + } + go func() { + mu.Lock() + for !done { + if tokens < maxTokens { + tokens++ + consumer.Signal() + } else { + generator.Wait() + } + } + mu.Unlock() + }() + pending.Wait() + mu.Lock() + done = true + generator.Signal() + mu.Unlock() + } + +} + +func BenchmarkThunderingHerd(b *testing.B) { + for i := 0; i < b.N; i++ { + done := NewVar(false) + tokens := NewVar(0) + pending := NewVar(0) + for range iter.N(1000) { + Atomically(VoidOperation(func(tx *Tx) { + tx.Set(pending, tx.Get(pending).(int)+1) + })) + go func() { + Atomically(VoidOperation(func(tx *Tx) { + t := tx.Get(tokens).(int) + if t > 0 { + tx.Set(tokens, t-1) + tx.Set(pending, tx.Get(pending).(int)-1) + } else { + tx.Retry() + } + })) + }() + } + go func() { + for Atomically(func(tx *Tx) interface{} { + if tx.Get(done).(bool) { + return false + } + tx.Assert(tx.Get(tokens).(int) < maxTokens) + tx.Set(tokens, tx.Get(tokens).(int)+1) + return true + }).(bool) { + } + }() + Atomically(VoidOperation(func(tx *Tx) { + tx.Assert(tx.Get(pending).(int) == 0) + })) + AtomicSet(done, true) + } +} |