aboutsummaryrefslogtreecommitdiff
path: root/tests/stm.go
diff options
context:
space:
mode:
Diffstat (limited to 'tests/stm.go')
-rw-r--r--tests/stm.go405
1 files changed, 18 insertions, 387 deletions
diff --git a/tests/stm.go b/tests/stm.go
index 49fcd25..13b375a 100644
--- a/tests/stm.go
+++ b/tests/stm.go
@@ -2,7 +2,6 @@ package stm
import (
"context"
- "fmt"
"math"
"runtime"
"sync"
@@ -15,6 +14,17 @@ import (
+const (
+ d = 100 * time.Millisecond
+)
+
+
+var (
+ t0 = time.Now()
+)
+
+
+
func TestValue(t *testing.T) {
v := New("hello")
g.TAssertEqual("hello", v.Load())
@@ -41,332 +51,6 @@ func TestInt32(t *testing.T) {
g.TAssertEqual(false, v.CompareAndSwap(0, 10))
}
-func BenchmarkInt64Add(b *testing.B) {
- v := NewInt64(0)
- for i := 0; i < b.N; i++ {
- v.Add(1)
- }
-}
-
-func BenchmarkIntInterfaceAdd(b *testing.B) {
- var v Int[int64] = NewInt64(0)
- for i := 0; i < b.N; i++ {
- v.Add(1)
- }
-}
-
-func BenchmarkStdlibInt64Add(b *testing.B) {
- var n int64
- for i := 0; i < b.N; i++ {
- atomic.AddInt64(&n, 1)
- }
-}
-
-func BenchmarkInterfaceStore(b *testing.B) {
- var v Interface[string] = New("hello")
- for i := 0; i < b.N; i++ {
- v.Store(fmt.Sprint(i))
- }
-}
-
-func BenchmarkValueStore(b *testing.B) {
- v := New("hello")
- for i := 0; i < b.N; i++ {
- v.Store(fmt.Sprint(i))
- }
-}
-
-func BenchmarkStdlibValueStore(b *testing.B) {
- v := atomic.Value{}
- for i := 0; i < b.N; i++ {
- v.Store(fmt.Sprint(i))
- }
-}
-
-func BenchmarkDeref(b *testing.B) {
- x := NewVar(0)
- for i := 0; i < b.N; i++ {
- Deref(x)
- }
-}
-
-func BenchmarkAtomicSet(b *testing.B) {
- x := NewVar(0)
- for i := 0; i < b.N; i++ {
- AtomicSet(x, 0)
- }
-}
-
-func BenchmarkIncrementSTM(b *testing.B) {
- for i := 0; i < b.N; i++ {
- // spawn 1000 goroutines that each increment x by 1
- x := NewVar(0)
- for i := 0; i < 1000; i++ {
- go Atomically(VoidOperation(func(tx *Tx) {
- cur := x.Get(tx)
- x.Set(tx, cur+1)
- }))
- }
- // wait for x to reach 1000
- Atomically(VoidOperation(func(tx *Tx) {
- tx.Assert(x.Get(tx) == 1000)
- }))
- }
-}
-
-func BenchmarkIncrementMutex(b *testing.B) {
- for i := 0; i < b.N; i++ {
- var mu sync.Mutex
- x := 0
- for i := 0; i < 1000; i++ {
- go func() {
- mu.Lock()
- x++
- mu.Unlock()
- }()
- }
- for {
- mu.Lock()
- read := x
- mu.Unlock()
- if read == 1000 {
- break
- }
- }
- }
-}
-
-func BenchmarkIncrementChannel(b *testing.B) {
- for i := 0; i < b.N; i++ {
- c := make(chan int, 1)
- c <- 0
- for i := 0; i < 1000; i++ {
- go func() {
- c <- 1 + <-c
- }()
- }
- for {
- read := <-c
- if read == 1000 {
- break
- }
- c <- read
- }
- }
-}
-
-func BenchmarkReadVarSTM(b *testing.B) {
- for i := 0; i < b.N; i++ {
- var wg sync.WaitGroup
- wg.Add(1000)
- x := NewVar(0)
- for i := 0; i < 1000; i++ {
- go func() {
- Deref(x)
- wg.Done()
- }()
- }
- wg.Wait()
- }
-}
-
-func BenchmarkReadVarMutex(b *testing.B) {
- for i := 0; i < b.N; i++ {
- var mu sync.Mutex
- var wg sync.WaitGroup
- wg.Add(1000)
- x := 0
- for i := 0; i < 1000; i++ {
- go func() {
- mu.Lock()
- _ = x
- mu.Unlock()
- wg.Done()
- }()
- }
- wg.Wait()
- }
-}
-
-func BenchmarkReadVarChannel(b *testing.B) {
- for i := 0; i < b.N; i++ {
- var wg sync.WaitGroup
- wg.Add(1000)
- c := make(chan int)
- close(c)
- for i := 0; i < 1000; i++ {
- go func() {
- <-c
- wg.Done()
- }()
- }
- wg.Wait()
- }
-}
-
-func parallelPingPongs(b *testing.B, n int) {
- var wg sync.WaitGroup
- wg.Add(n)
- for i := 0; i < n; i++ {
- go func() {
- defer wg.Done()
- testPingPong(b, b.N, func(string) {})
- }()
- }
- wg.Wait()
-}
-
-func BenchmarkPingPong4(b *testing.B) {
- b.ReportAllocs()
- parallelPingPongs(b, 4)
-}
-
-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 i := 0; i < 1000; i++ {
- 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 i := 0; i < 1000; i++ {
- Atomically(VoidOperation(func(tx *Tx) {
- pending.Set(tx, pending.Get(tx)+1)
- }))
- go func() {
- Atomically(VoidOperation(func(tx *Tx) {
- t := tokens.Get(tx)
- if t > 0 {
- tokens.Set(tx, t-1)
- pending.Set(tx, pending.Get(tx)-1)
- } else {
- tx.Retry()
- }
- }))
- }()
- }
- go func() {
- for Atomically(func(tx *Tx) bool {
- if done.Get(tx) {
- return false
- }
- tx.Assert(tokens.Get(tx) < maxTokens)
- tokens.Set(tx, tokens.Get(tx)+1)
- return true
- }) {
- }
- }()
- Atomically(VoidOperation(func(tx *Tx) {
- tx.Assert(pending.Get(tx) == 0)
- }))
- AtomicSet(done, true)
- }
-}
-
-func BenchmarkInvertedThunderingHerd(b *testing.B) {
- for i := 0; i < b.N; i++ {
- done := NewBuiltinEqVar(false)
- tokens := NewBuiltinEqVar(0)
- pending := NewVar(NewSet[*Var[bool]]())
- for i := 0; i < 1000; i++ {
- ready := NewVar(false)
- Atomically(VoidOperation(func(tx *Tx) {
- pending.Set(tx, pending.Get(tx).Add(ready))
- }))
- go func() {
- Atomically(VoidOperation(func(tx *Tx) {
- tx.Assert(ready.Get(tx))
- set := pending.Get(tx)
- if !set.Contains(ready) {
- panic("couldn't find ourselves in pending")
- }
- pending.Set(tx, set.Delete(ready))
- }))
- //b.Log("waiter finished")
- }()
- }
- go func() {
- for Atomically(func(tx *Tx) bool {
- if done.Get(tx) {
- return false
- }
- tx.Assert(tokens.Get(tx) < maxTokens)
- tokens.Set(tx, tokens.Get(tx)+1)
- return true
- }) {
- }
- }()
- go func() {
- for Atomically(func(tx *Tx) bool {
- tx.Assert(tokens.Get(tx) > 0)
- tokens.Set(tx, tokens.Get(tx)-1)
- pending.Get(tx).Range(func(ready *Var[bool]) bool {
- if !ready.Get(tx) {
- ready.Set(tx, true)
- return false
- }
- return true
- })
- return !done.Get(tx)
- }) {
- }
- }()
- Atomically(VoidOperation(func(tx *Tx) {
- tx.Assert(pending.Get(tx).(Lenner).Len() == 0)
- }))
- AtomicSet(done, true)
- }
-}
-
func TestLimit(t *testing.T) {
if Limit(10) == Inf {
t.Errorf("Limit(10) == Inf should be false")
@@ -404,26 +88,6 @@ func TestEvery(t *testing.T) {
}
}
-const (
- d = 100 * time.Millisecond
-)
-
-var (
- t0 = time.Now()
- t1 = t0.Add(time.Duration(1) * d)
- t2 = t0.Add(time.Duration(2) * d)
- t3 = t0.Add(time.Duration(3) * d)
- t4 = t0.Add(time.Duration(4) * d)
- t5 = t0.Add(time.Duration(5) * d)
- t9 = t0.Add(time.Duration(9) * d)
-)
-
-type allow struct {
- t time.Time
- n int
- ok bool
-}
-
//
//func run(t *testing.T, lim *Limiter, allows []allow) {
// for i, allow := range allows {
@@ -576,25 +240,6 @@ func TestLongRunningQPS(t *testing.T) {
}
}
-type request struct {
- t time.Time
- n int
- act time.Time
- ok bool
-}
-
-// dFromDuration converts a duration to a multiple of the global constant d
-func dFromDuration(dur time.Duration) int {
- // Adding a millisecond to be swallowed by the integer division
- // because we don't care about small inaccuracies
- return int((dur + time.Millisecond) / d)
-}
-
-// dSince returns multiples of d since t0
-func dSince(t time.Time) int {
- return dFromDuration(t.Sub(t0))
-}
-
//
//func runReserve(t *testing.T, lim *Limiter, req request) *Reservation {
// return runReserveMax(t, lim, req, InfDuration)
@@ -750,6 +395,13 @@ type wait struct {
nilErr bool
}
+// dFromDuration converts a duration to a multiple of the global constant d
+func dFromDuration(dur time.Duration) int {
+ // Adding a millisecond to be swallowed by the integer division
+ // because we don't care about small inaccuracies
+ return int((dur + time.Millisecond) / d)
+}
+
func runWait(t *testing.T, lim *Limiter, w wait) {
t.Helper()
start := time.Now()
@@ -808,27 +460,6 @@ func TestWaitInf(t *testing.T) {
runWait(t, lim, wait{"exceed-burst-no-error", context.Background(), 3, 0, true})
}
-func BenchmarkAllowN(b *testing.B) {
- lim := NewLimiter(Every(1*time.Second), 1)
- b.ReportAllocs()
- b.ResetTimer()
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- lim.AllowN(1)
- }
- })
-}
-
-func BenchmarkWaitNNoDelay(b *testing.B) {
- lim := NewLimiter(Limit(b.N), b.N)
- ctx := context.Background()
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- lim.WaitN(ctx, 1)
- }
-}
-
func TestDecrement(t *testing.T) {
x := NewVar(1000)
for i := 0; i < 500; i++ {