github.com/fufuok/utils@v1.0.10/xsync/counter_test.go (about)

     1  package xsync_test
     2  
     3  import (
     4  	"runtime"
     5  	"sync/atomic"
     6  	"testing"
     7  
     8  	. "github.com/fufuok/utils/xsync"
     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  }