github.com/moontrade/nogc@v0.1.7/collections/queue/lock_free_test.go (about)

     1  package queue
     2  
     3  import (
     4  	"github.com/moontrade/nogc"
     5  	"runtime"
     6  	"sync"
     7  	"sync/atomic"
     8  	"testing"
     9  )
    10  
    11  func TestLockFreeQueue(t *testing.T) {
    12  	const taskNum = 50000000
    13  	nogc.AllocZeroed(24)
    14  	q := AllocLockFreeQueue()
    15  
    16  	b := nogc.AllocBytes(24)
    17  	b.Free()
    18  
    19  	var wg sync.WaitGroup
    20  	goroutines := 100
    21  	wg.Add(goroutines)
    22  	for i := 0; i < goroutines; i++ {
    23  		go func() {
    24  			defer wg.Done()
    25  			for i := 0; i < taskNum/goroutines; i++ {
    26  				task := nogc.AllocBytes(24)
    27  				q.Enqueue(task)
    28  			}
    29  		}()
    30  	}
    31  
    32  	var counter int32
    33  	wg.Add(goroutines)
    34  	for i := 0; i < goroutines; i++ {
    35  		go func() {
    36  			defer wg.Done()
    37  			for {
    38  				task := q.Dequeue()
    39  				if !task.IsNil() {
    40  					atomic.AddInt32(&counter, 1)
    41  					task.Free()
    42  				} else {
    43  					break
    44  				}
    45  			}
    46  		}()
    47  	}
    48  
    49  	wg.Wait()
    50  
    51  	t.Logf("sent and received all %d tasks", taskNum)
    52  }
    53  
    54  func Benchmark(b *testing.B) {
    55  	b.Run("queue", func(b *testing.B) {
    56  		value := nogc.BytesOfString("hello")
    57  		q := AllocLockFreeQueue()
    58  		wg := &sync.WaitGroup{}
    59  		startWg := &sync.WaitGroup{}
    60  		startWg.Add(1)
    61  
    62  		wg.Add(1)
    63  		go func() {
    64  			defer wg.Done()
    65  			runtime.LockOSThread()
    66  			defer runtime.UnlockOSThread()
    67  			startWg.Wait()
    68  			b.ResetTimer()
    69  			b.ReportAllocs()
    70  			for i := 0; i < b.N; i++ {
    71  				q.Enqueue(value)
    72  			}
    73  		}()
    74  		wg.Add(1)
    75  		go func() {
    76  			defer wg.Done()
    77  			runtime.LockOSThread()
    78  			defer runtime.UnlockOSThread()
    79  			startWg.Wait()
    80  			count := 0
    81  			var v nogc.Bytes
    82  			for {
    83  				if count >= b.N {
    84  					break
    85  				}
    86  				v = q.Dequeue()
    87  				if !v.IsNil() {
    88  					count++
    89  				}
    90  			}
    91  		}()
    92  
    93  		startWg.Done()
    94  		wg.Wait()
    95  	})
    96  
    97  	b.Run("chan buf 1", func(b *testing.B) {
    98  		value := nogc.BytesOfString("hello")
    99  		wg := &sync.WaitGroup{}
   100  		startWg := &sync.WaitGroup{}
   101  		startWg.Add(1)
   102  
   103  		ch := make(chan nogc.Bytes, 64)
   104  		defer close(ch)
   105  
   106  		wg.Add(1)
   107  		go func() {
   108  			defer wg.Done()
   109  			startWg.Wait()
   110  			b.ResetTimer()
   111  			b.ReportAllocs()
   112  			for i := 0; i < b.N; i++ {
   113  				ch <- value
   114  			}
   115  		}()
   116  		wg.Add(1)
   117  		go func() {
   118  			defer wg.Done()
   119  			startWg.Wait()
   120  			count := 0
   121  			var v nogc.Bytes
   122  			for {
   123  				if count >= b.N {
   124  					break
   125  				}
   126  				v = <-ch
   127  				if !v.IsNil() {
   128  					count++
   129  				}
   130  			}
   131  		}()
   132  
   133  		startWg.Done()
   134  		wg.Wait()
   135  	})
   136  }