github.com/reusee/pr3@v0.0.0-20240520031754-49012a37a83e/pool_test.go (about)

     1  package pr3
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math/rand"
     7  	"sync"
     8  	"sync/atomic"
     9  	"testing"
    10  )
    11  
    12  func TestBytesPool(t *testing.T) {
    13  	pool := NewPool(8, func() []byte {
    14  		return make([]byte, 8)
    15  	})
    16  	wg := new(sync.WaitGroup)
    17  	for i := 0; i < 200; i++ {
    18  		wg.Add(1)
    19  		i := i
    20  		go func() {
    21  			defer wg.Done()
    22  			for j := 0; j < 200; j++ {
    23  				var bs []byte
    24  				elem := pool.Get(&bs)
    25  				defer elem.Put()
    26  				binary.PutUvarint(bs, uint64(i))
    27  			}
    28  		}()
    29  	}
    30  	wg.Wait()
    31  }
    32  
    33  func TestBytesPoolRC(t *testing.T) {
    34  	pool := NewPool(8, func() []byte {
    35  		return make([]byte, 8)
    36  	})
    37  	wg := new(sync.WaitGroup)
    38  	for i := 0; i < 200; i++ {
    39  		wg.Add(1)
    40  		i := i
    41  		go func() {
    42  			defer wg.Done()
    43  			for j := 0; j < 200; j++ {
    44  				var bs []byte
    45  				elem := pool.Get(&bs)
    46  				defer elem.Put()
    47  				nRef := rand.Intn(16)
    48  				for i := 0; i < nRef; i++ {
    49  					elem.Inc()
    50  				}
    51  				defer func() {
    52  					for i := 0; i < nRef; i++ {
    53  						elem.Inc()
    54  					}
    55  				}()
    56  				binary.PutUvarint(bs, uint64(i))
    57  			}
    58  		}()
    59  	}
    60  	wg.Wait()
    61  }
    62  
    63  func TestBytesPoolRCOverload(t *testing.T) {
    64  	pool := NewPool(1, func() int {
    65  		return 42
    66  	})
    67  	var i int
    68  	pool.Get(&i)
    69  	var j int
    70  	elem := pool.Get(&j)
    71  	elem.Inc()
    72  	if elem.Put() {
    73  		t.Fatal()
    74  	}
    75  	if !elem.Put() {
    76  		t.Fatal()
    77  	}
    78  }
    79  
    80  func BenchmarkBytesPool(b *testing.B) {
    81  	pool := NewPool(8, func() []byte {
    82  		return make([]byte, 8)
    83  	})
    84  	b.ResetTimer()
    85  	for i := 0; i < b.N; i++ {
    86  		var v []byte
    87  		elem := pool.Get(&v)
    88  		elem.Put()
    89  	}
    90  }
    91  
    92  func BenchmarkStdSyncPool(b *testing.B) {
    93  	pool := &sync.Pool{
    94  		New: func() any {
    95  			bs := make([]byte, 8)
    96  			return &bs
    97  		},
    98  	}
    99  	b.ResetTimer()
   100  	for i := 0; i < b.N; i++ {
   101  		elem := pool.Get().(*[]byte)
   102  		pool.Put(elem)
   103  	}
   104  }
   105  
   106  func BenchmarkParallelBytesPool(b *testing.B) {
   107  	pool := NewPool(1024, func() []byte {
   108  		return make([]byte, 8)
   109  	})
   110  	b.ResetTimer()
   111  	b.RunParallel(func(pb *testing.PB) {
   112  		for pb.Next() {
   113  			var v []byte
   114  			elem := pool.Get(&v)
   115  			elem.Put()
   116  		}
   117  	})
   118  }
   119  
   120  func BenchmarkParallelStdSyncPool(b *testing.B) {
   121  	pool := &sync.Pool{
   122  		New: func() any {
   123  			bs := make([]byte, 8)
   124  			return &bs
   125  		},
   126  	}
   127  	b.ResetTimer()
   128  	b.RunParallel(func(pb *testing.PB) {
   129  		for pb.Next() {
   130  			elem := pool.Get().(*[]byte)
   131  			pool.Put(elem)
   132  		}
   133  	})
   134  }
   135  
   136  func TestPoolBadPut(t *testing.T) {
   137  	pool := NewPool(1, func() int {
   138  		return 42
   139  	})
   140  	var i int
   141  	elem := pool.Get(&i)
   142  	elem.Put()
   143  	func() {
   144  		defer func() {
   145  			p := recover()
   146  			if p == nil {
   147  				t.Fatal()
   148  			}
   149  			if fmt.Sprintf("%v", p) != "bad put" {
   150  				t.Fatal()
   151  			}
   152  		}()
   153  		elem.Put()
   154  	}()
   155  }
   156  
   157  func TestPoolBadPutRC(t *testing.T) {
   158  	pool := NewPool(1, func() int {
   159  		return 42
   160  	})
   161  	var j int
   162  	pool.Get(&j)
   163  	var i int
   164  	elem := pool.Get(&i)
   165  	elem.Put()
   166  	func() {
   167  		defer func() {
   168  			p := recover()
   169  			if p == nil {
   170  				t.Fatal()
   171  			}
   172  			if fmt.Sprintf("%v", p) != "bad put" {
   173  				t.Fatal()
   174  			}
   175  		}()
   176  		elem.Put()
   177  	}()
   178  }
   179  
   180  func BenchmarkPoolDrain(b *testing.B) {
   181  	pool := NewPool(1, func() []byte {
   182  		return make([]byte, 8)
   183  	})
   184  	b.ResetTimer()
   185  	b.RunParallel(func(pb *testing.PB) {
   186  		for pb.Next() {
   187  			var v []byte
   188  			elem := pool.Get(&v)
   189  			elem.Put()
   190  		}
   191  	})
   192  }
   193  
   194  func BenchmarkFastrand(b *testing.B) {
   195  	for i := 0; i < b.N; i++ {
   196  		fastrand()
   197  	}
   198  }
   199  
   200  func BenchmarkAtomicAdd(b *testing.B) {
   201  	n := new(atomic.Uint32)
   202  	for i := 0; i < b.N; i++ {
   203  		n.Add(1)
   204  	}
   205  }