aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Joiner <anacrolix@gmail.com>2020-09-10 09:22:29 +1000
committerMatt Joiner <anacrolix@gmail.com>2020-09-10 09:22:35 +1000
commit672853d0af1972bf15d37596358009eebe5f6d4f (patch)
tree42b54a3912deb4fb644612b5b7482125d0115f3d
parentAdd custom VarValue and const for sleep backoff (diff)
downloadstm-672853d0af1972bf15d37596358009eebe5f6d4f.tar.gz
stm-672853d0af1972bf15d37596358009eebe5f6d4f.tar.xz
Move some benchmarks to be external tests
-rw-r--r--bench_test.go86
-rw-r--r--external_test.go152
2 files changed, 152 insertions, 86 deletions
diff --git a/bench_test.go b/bench_test.go
index da2bf97..82aaba1 100644
--- a/bench_test.go
+++ b/bench_test.go
@@ -149,89 +149,3 @@ 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 := NewBuiltinEqVar(false)
- tokens := NewBuiltinEqVar(0)
- pending := NewBuiltinEqVar(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)
- }
-}
diff --git a/external_test.go b/external_test.go
new file mode 100644
index 0000000..ae29ca8
--- /dev/null
+++ b/external_test.go
@@ -0,0 +1,152 @@
+package stm_test
+
+import (
+ "sync"
+ "testing"
+
+ "github.com/anacrolix/missinggo/iter"
+ "github.com/anacrolix/stm"
+ "github.com/anacrolix/stm/stmutil"
+)
+
+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 := stm.NewBuiltinEqVar(false)
+ tokens := stm.NewBuiltinEqVar(0)
+ pending := stm.NewBuiltinEqVar(0)
+ for range iter.N(1000) {
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ tx.Set(pending, tx.Get(pending).(int)+1)
+ }))
+ go func() {
+ stm.Atomically(stm.VoidOperation(func(tx *stm.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 stm.Atomically(func(tx *stm.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) {
+ }
+ }()
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ tx.Assert(tx.Get(pending).(int) == 0)
+ }))
+ stm.AtomicSet(done, true)
+ }
+}
+
+func BenchmarkInvertedThunderingHerd(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ done := stm.NewBuiltinEqVar(false)
+ tokens := stm.NewBuiltinEqVar(0)
+ pending := stm.NewVar(stmutil.NewSet())
+ for range iter.N(1000) {
+ ready := stm.NewVar(false)
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ tx.Set(pending, tx.Get(pending).(stmutil.Settish).Add(ready))
+ }))
+ go func() {
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ tx.Assert(tx.Get(ready).(bool))
+ set := tx.Get(pending).(stmutil.Settish)
+ if !set.Contains(ready) {
+ panic("couldn't find ourselves in pending")
+ }
+ tx.Set(pending, set.Delete(ready))
+ }))
+ //b.Log("waiter finished")
+ }()
+ }
+ go func() {
+ for stm.Atomically(func(tx *stm.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) {
+ }
+ }()
+ go func() {
+ for stm.Atomically(func(tx *stm.Tx) interface{} {
+ tx.Assert(tx.Get(tokens).(int) > 0)
+ tx.Set(tokens, tx.Get(tokens).(int)-1)
+ tx.Get(pending).(stmutil.Settish).Range(func(i interface{}) bool {
+ ready := i.(*stm.Var)
+ if !tx.Get(ready).(bool) {
+ tx.Set(ready, true)
+ return false
+ }
+ return true
+ })
+ return !tx.Get(done).(bool)
+ }).(bool) {
+ }
+ }()
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ tx.Assert(tx.Get(pending).(stmutil.Lenner).Len() == 0)
+ }))
+ stm.AtomicSet(done, true)
+ }
+}