github.com/alphadose/zenq/v2@v2.8.4/benchmarks/e2e/benchsuite_test.go (about)

     1  package zenq_test
     2  
     3  import (
     4  	"sync"
     5  	"testing"
     6  
     7  	"github.com/alphadose/zenq/v2"
     8  )
     9  
    10  // wrapper for chan to have exactly the same api as zenq.
    11  type Chan[T any] struct {
    12  	ch chan T
    13  }
    14  
    15  func NewChan[T any]() Chan[T] {
    16  	return Chan[T]{ch: make(chan T, bufferSize)}
    17  }
    18  
    19  func (ch Chan[T]) Read() T   { return <-ch.ch }
    20  func (ch Chan[T]) Write(v T) { ch.ch <- v }
    21  
    22  func BenchmarkChan_Suite(b *testing.B) {
    23  	type Queue = Chan[int]
    24  	ctor := NewChan[int]
    25  
    26  	b.Run("Single", func(b *testing.B) {
    27  		q := ctor()
    28  		b.ResetTimer()
    29  		for i := 0; i < b.N; i++ {
    30  			q.Write(i)
    31  			_ = q.Read()
    32  		}
    33  	})
    34  
    35  	b.Run("Uncontended/x100", func(b *testing.B) {
    36  		b.RunParallel(func(pb *testing.PB) {
    37  			q := ctor()
    38  			for pb.Next() {
    39  				for i := 0; i < 100; i++ {
    40  					q.Write(i)
    41  					_ = q.Read()
    42  				}
    43  			}
    44  		})
    45  	})
    46  
    47  	b.Run("Contended/x100", func(b *testing.B) {
    48  		q := ctor()
    49  		b.RunParallel(func(pb *testing.PB) {
    50  			for pb.Next() {
    51  				for i := 0; i < 100; i++ {
    52  					q.Write(i)
    53  					_ = q.Read()
    54  				}
    55  			}
    56  		})
    57  	})
    58  
    59  	b.Run("Multiple/x100", func(b *testing.B) {
    60  		const P = 1000
    61  		qs := [P]Queue{}
    62  		for i := range qs {
    63  			qs[i] = ctor()
    64  		}
    65  
    66  		b.ResetTimer()
    67  
    68  		var wg sync.WaitGroup
    69  		wg.Add(P * 2)
    70  		for i := 0; i < P; i++ {
    71  			go func(q Queue) {
    72  				defer wg.Done()
    73  				for i := 0; i < b.N; i++ {
    74  					var v int
    75  					q.Write(v)
    76  				}
    77  			}(qs[i])
    78  			go func(q Queue) {
    79  				defer wg.Done()
    80  				for i := 0; i < b.N; i++ {
    81  					_ = q.Read()
    82  				}
    83  
    84  			}(qs[i])
    85  		}
    86  		wg.Wait()
    87  	})
    88  
    89  	b.Run("ProducerConsumer/x1", func(b *testing.B) {
    90  		q := ctor()
    91  		b.ResetTimer()
    92  		var wg sync.WaitGroup
    93  		wg.Add(2)
    94  		go func() {
    95  			defer wg.Done()
    96  			for i := 0; i < b.N; i++ {
    97  				var v int
    98  				q.Write(v)
    99  				work()
   100  			}
   101  		}()
   102  
   103  		go func() {
   104  			defer wg.Done()
   105  			for i := 0; i < b.N; i++ {
   106  				_ = q.Read()
   107  				work()
   108  			}
   109  		}()
   110  		wg.Wait()
   111  	})
   112  
   113  	b.Run("ProducerConsumer/x100", func(b *testing.B) {
   114  		q := ctor()
   115  		b.ResetTimer()
   116  		var wg sync.WaitGroup
   117  		wg.Add(2)
   118  
   119  		go func() {
   120  			b.RunParallel(func(pb *testing.PB) {
   121  				for pb.Next() {
   122  					for i := 0; i < 100; i++ {
   123  						q.Write(0)
   124  						work()
   125  					}
   126  				}
   127  			})
   128  			wg.Done()
   129  		}()
   130  
   131  		go func() {
   132  			b.RunParallel(func(pb *testing.PB) {
   133  				for pb.Next() {
   134  					for i := 0; i < 100; i++ {
   135  						_ = q.Read()
   136  						work()
   137  					}
   138  				}
   139  			})
   140  			wg.Done()
   141  		}()
   142  		wg.Wait()
   143  	})
   144  
   145  	b.Run("PingPong/x1", func(b *testing.B) {
   146  		q1 := ctor()
   147  		q2 := ctor()
   148  		b.ResetTimer()
   149  		var wg sync.WaitGroup
   150  		wg.Add(2)
   151  
   152  		go func() {
   153  			for i := 0; i < b.N; i++ {
   154  				var v int
   155  				q1.Write(v)
   156  				work()
   157  				_ = q2.Read()
   158  			}
   159  			wg.Done()
   160  		}()
   161  
   162  		go func() {
   163  			for i := 0; i < b.N; i++ {
   164  				var v int
   165  				_ = q1.Read()
   166  				work()
   167  				q2.Write(v)
   168  			}
   169  			wg.Done()
   170  		}()
   171  		wg.Wait()
   172  	})
   173  }
   174  
   175  func BenchmarkZenq_Suite(b *testing.B) {
   176  	type Queue = zenq.ZenQ[int]
   177  	ctor := zenq.New[int]
   178  
   179  	b.Run("Single", func(b *testing.B) {
   180  		q := ctor(bufferSize)
   181  		b.ResetTimer()
   182  		for i := 0; i < b.N; i++ {
   183  			q.Write(i)
   184  			_, _ = q.Read()
   185  		}
   186  	})
   187  
   188  	b.Run("Uncontended/x100", func(b *testing.B) {
   189  		b.RunParallel(func(pb *testing.PB) {
   190  			q := ctor(bufferSize)
   191  			for pb.Next() {
   192  				for i := 0; i < 100; i++ {
   193  					q.Write(i)
   194  					_, _ = q.Read()
   195  				}
   196  			}
   197  		})
   198  	})
   199  
   200  	b.Run("Contended/x100", func(b *testing.B) {
   201  		q := ctor(bufferSize)
   202  		b.RunParallel(func(pb *testing.PB) {
   203  			for pb.Next() {
   204  				for i := 0; i < 100; i++ {
   205  					q.Write(i)
   206  					_, _ = q.Read()
   207  				}
   208  			}
   209  		})
   210  	})
   211  
   212  	b.Run("Multiple/x100", func(b *testing.B) {
   213  		const P = 1000
   214  		qs := [P]*Queue{}
   215  		for i := range qs {
   216  			qs[i] = ctor(bufferSize)
   217  		}
   218  
   219  		b.ResetTimer()
   220  
   221  		var wg sync.WaitGroup
   222  		wg.Add(P * 2)
   223  		for i := 0; i < P; i++ {
   224  			go func(q *Queue) {
   225  				defer wg.Done()
   226  				for i := 0; i < b.N; i++ {
   227  					var v int
   228  					q.Write(v)
   229  				}
   230  			}(qs[i])
   231  			go func(q *Queue) {
   232  				defer wg.Done()
   233  				for i := 0; i < b.N; i++ {
   234  					_, _ = q.Read()
   235  				}
   236  
   237  			}(qs[i])
   238  		}
   239  		wg.Wait()
   240  	})
   241  
   242  	b.Run("ProducerConsumer/x1", func(b *testing.B) {
   243  		q := ctor(bufferSize)
   244  		b.ResetTimer()
   245  		var wg sync.WaitGroup
   246  		wg.Add(2)
   247  		go func() {
   248  			defer wg.Done()
   249  			for i := 0; i < b.N; i++ {
   250  				var v int
   251  				q.Write(v)
   252  				work()
   253  			}
   254  		}()
   255  
   256  		go func() {
   257  			defer wg.Done()
   258  			for i := 0; i < b.N; i++ {
   259  				_, _ = q.Read()
   260  				work()
   261  			}
   262  		}()
   263  		wg.Wait()
   264  	})
   265  
   266  	b.Run("ProducerConsumer/x100", func(b *testing.B) {
   267  		q := ctor(bufferSize)
   268  		b.ResetTimer()
   269  		var wg sync.WaitGroup
   270  		wg.Add(2)
   271  
   272  		go func() {
   273  			b.RunParallel(func(pb *testing.PB) {
   274  				for pb.Next() {
   275  					for i := 0; i < 100; i++ {
   276  						q.Write(0)
   277  						work()
   278  					}
   279  				}
   280  			})
   281  			wg.Done()
   282  		}()
   283  
   284  		go func() {
   285  			b.RunParallel(func(pb *testing.PB) {
   286  				for pb.Next() {
   287  					for i := 0; i < 100; i++ {
   288  						_, _ = q.Read()
   289  						work()
   290  					}
   291  				}
   292  			})
   293  			wg.Done()
   294  		}()
   295  		wg.Wait()
   296  	})
   297  
   298  	b.Run("PingPong/x1", func(b *testing.B) {
   299  		q1 := ctor(bufferSize)
   300  		q2 := ctor(bufferSize)
   301  		b.ResetTimer()
   302  		var wg sync.WaitGroup
   303  		wg.Add(2)
   304  
   305  		go func() {
   306  			for i := 0; i < b.N; i++ {
   307  				var v int
   308  				q1.Write(v)
   309  				work()
   310  				_, _ = q2.Read()
   311  			}
   312  			wg.Done()
   313  		}()
   314  
   315  		go func() {
   316  			for i := 0; i < b.N; i++ {
   317  				var v int
   318  				_, _ = q1.Read()
   319  				work()
   320  				q2.Write(v)
   321  			}
   322  			wg.Done()
   323  		}()
   324  		wg.Wait()
   325  	})
   326  }
   327  
   328  //go:noinline
   329  func work() {
   330  	// really tiny amount of work
   331  }