github.com/puzpuzpuz/xsync/v2@v2.5.2-0.20231021165734-92b8269e19a9/counter_test.go (about) 1 package xsync_test 2 3 import ( 4 "runtime" 5 "sync/atomic" 6 "testing" 7 8 . "github.com/puzpuzpuz/xsync/v2" 9 ) 10 11 func TestCounterInc(t *testing.T) { 12 c := NewCounter() 13 for i := 0; i < 100; i++ { 14 if v := c.Value(); v != int64(i) { 15 t.Fatalf("got %v, want %d", v, i) 16 } 17 c.Inc() 18 } 19 } 20 21 func TestCounterDec(t *testing.T) { 22 c := NewCounter() 23 for i := 0; i < 100; i++ { 24 if v := c.Value(); v != int64(-i) { 25 t.Fatalf("got %v, want %d", v, -i) 26 } 27 c.Dec() 28 } 29 } 30 31 func TestCounterAdd(t *testing.T) { 32 c := NewCounter() 33 for i := 0; i < 100; i++ { 34 if v := c.Value(); v != int64(i*42) { 35 t.Fatalf("got %v, want %d", v, i*42) 36 } 37 c.Add(42) 38 } 39 } 40 41 func TestCounterReset(t *testing.T) { 42 c := NewCounter() 43 c.Add(42) 44 if v := c.Value(); v != 42 { 45 t.Fatalf("got %v, want %d", v, 42) 46 } 47 c.Reset() 48 if v := c.Value(); v != 0 { 49 t.Fatalf("got %v, want %d", v, 0) 50 } 51 } 52 53 func parallelIncrementor(c *Counter, numIncs int, cdone chan bool) { 54 for i := 0; i < numIncs; i++ { 55 c.Inc() 56 } 57 cdone <- true 58 } 59 60 func doTestParallelIncrementors(t *testing.T, numModifiers, gomaxprocs int) { 61 runtime.GOMAXPROCS(gomaxprocs) 62 c := NewCounter() 63 cdone := make(chan bool) 64 numIncs := 10_000 65 for i := 0; i < numModifiers; i++ { 66 go parallelIncrementor(c, numIncs, cdone) 67 } 68 // Wait for the goroutines to finish. 69 for i := 0; i < numModifiers; i++ { 70 <-cdone 71 } 72 expected := int64(numModifiers * numIncs) 73 if v := c.Value(); v != expected { 74 t.Fatalf("got %d, want %d", v, expected) 75 } 76 } 77 78 func TestCounterParallelIncrementors(t *testing.T) { 79 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1)) 80 doTestParallelIncrementors(t, 4, 2) 81 doTestParallelIncrementors(t, 16, 4) 82 doTestParallelIncrementors(t, 64, 8) 83 } 84 85 func benchmarkCounter(b *testing.B, writeRatio int) { 86 c := NewCounter() 87 runParallel(b, func(pb *testing.PB) { 88 foo := 0 89 for pb.Next() { 90 foo++ 91 if writeRatio > 0 && foo%writeRatio == 0 { 92 c.Value() 93 } else { 94 c.Inc() 95 } 96 } 97 _ = foo 98 }) 99 } 100 101 func BenchmarkCounter(b *testing.B) { 102 benchmarkCounter(b, 10000) 103 } 104 105 func benchmarkAtomicInt64(b *testing.B, writeRatio int) { 106 var c int64 107 runParallel(b, func(pb *testing.PB) { 108 foo := 0 109 for pb.Next() { 110 foo++ 111 if writeRatio > 0 && foo%writeRatio == 0 { 112 atomic.LoadInt64(&c) 113 } else { 114 atomic.AddInt64(&c, 1) 115 } 116 } 117 _ = foo 118 }) 119 } 120 121 func BenchmarkAtomicInt64(b *testing.B) { 122 benchmarkAtomicInt64(b, 10000) 123 }