github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/collection/lscq/bench_test.go (about)

     1  // Copyright 2021 ByteDance Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package lscq
    16  
    17  import (
    18  	"sync/atomic"
    19  	"testing"
    20  
    21  	"github.com/bytedance/gopkg/internal/benchmark/linkedq"
    22  	"github.com/bytedance/gopkg/internal/benchmark/msq"
    23  	"github.com/bytedance/gopkg/lang/fastrand"
    24  )
    25  
    26  type uint64queue interface {
    27  	Enqueue(uint64) bool
    28  	Dequeue() (uint64, bool)
    29  }
    30  
    31  type benchTask struct {
    32  	name string
    33  	New  func() uint64queue
    34  }
    35  
    36  type faa int64
    37  
    38  func (data *faa) Enqueue(_ uint64) bool {
    39  	atomic.AddInt64((*int64)(data), 1)
    40  	return true
    41  }
    42  
    43  func (data *faa) Dequeue() (uint64, bool) {
    44  	atomic.AddInt64((*int64)(data), -1)
    45  	return 0, false
    46  }
    47  
    48  func BenchmarkDefault(b *testing.B) {
    49  	all := []benchTask{{
    50  		name: "LSCQ", New: func() uint64queue {
    51  			return NewUint64()
    52  		}}}
    53  	all = append(all, benchTask{
    54  		name: "LinkedQueue",
    55  		New: func() uint64queue {
    56  			return linkedq.New()
    57  		},
    58  	})
    59  	all = append(all, benchTask{
    60  		name: "MSQueue",
    61  		New: func() uint64queue {
    62  			return msq.New()
    63  		},
    64  	})
    65  	// all = append(all, benchTask{
    66  	// 	name: "FAA",
    67  	// 	New: func() uint64queue {
    68  	// 		return new(faa)
    69  	// 	},
    70  	// })
    71  	// all = append(all, benchTask{
    72  	// 	name: "channel",
    73  	// 	New: func() uint64queue {
    74  	// 		return newChannelQ(scqsize)
    75  	// 	},
    76  	// })
    77  	benchEnqueueOnly(b, all)
    78  	benchDequeueOnlyEmpty(b, all)
    79  	benchPair(b, all)
    80  	bench50Enqueue50Dequeue(b, all)
    81  	bench30Enqueue70Dequeue(b, all)
    82  	bench70Enqueue30Dequeue(b, all)
    83  }
    84  
    85  func reportalloc(b *testing.B) {
    86  	// b.SetBytes(8)
    87  	// b.ReportAllocs()
    88  }
    89  
    90  func benchPair(b *testing.B, benchTasks []benchTask) {
    91  	for _, v := range benchTasks {
    92  		b.Run("Pair/"+v.name, func(b *testing.B) {
    93  			q := v.New()
    94  			reportalloc(b)
    95  			b.ResetTimer()
    96  			b.RunParallel(func(pb *testing.PB) {
    97  				for pb.Next() {
    98  					q.Enqueue(uint64(fastrand.Uint32()))
    99  					q.Dequeue()
   100  				}
   101  			})
   102  		})
   103  	}
   104  }
   105  
   106  func bench50Enqueue50Dequeue(b *testing.B, benchTasks []benchTask) {
   107  	for _, v := range benchTasks {
   108  		b.Run("50Enqueue50Dequeue/"+v.name, func(b *testing.B) {
   109  			q := v.New()
   110  			b.ResetTimer()
   111  			reportalloc(b)
   112  			b.RunParallel(func(pb *testing.PB) {
   113  				for pb.Next() {
   114  					if fastrand.Uint32n(2) == 0 {
   115  						q.Enqueue(uint64(fastrand.Uint32()))
   116  					} else {
   117  						q.Dequeue()
   118  					}
   119  				}
   120  			})
   121  		})
   122  	}
   123  }
   124  
   125  func bench70Enqueue30Dequeue(b *testing.B, benchTasks []benchTask) {
   126  	for _, v := range benchTasks {
   127  		b.Run("70Enqueue30Dequeue/"+v.name, func(b *testing.B) {
   128  			q := v.New()
   129  			reportalloc(b)
   130  			b.ResetTimer()
   131  			b.RunParallel(func(pb *testing.PB) {
   132  				for pb.Next() {
   133  					if fastrand.Uint32n(10) > 2 {
   134  						q.Enqueue(uint64(fastrand.Uint32()))
   135  					} else {
   136  						q.Dequeue()
   137  					}
   138  				}
   139  			})
   140  		})
   141  	}
   142  }
   143  
   144  func bench30Enqueue70Dequeue(b *testing.B, benchTasks []benchTask) {
   145  	for _, v := range benchTasks {
   146  		b.Run("30Enqueue70Dequeue/"+v.name, func(b *testing.B) {
   147  			q := v.New()
   148  			reportalloc(b)
   149  			b.ResetTimer()
   150  			b.RunParallel(func(pb *testing.PB) {
   151  				for pb.Next() {
   152  					if fastrand.Uint32n(10) <= 2 {
   153  						q.Enqueue(uint64(fastrand.Uint32()))
   154  					} else {
   155  						q.Dequeue()
   156  					}
   157  				}
   158  			})
   159  		})
   160  	}
   161  }
   162  
   163  func benchEnqueueOnly(b *testing.B, benchTasks []benchTask) {
   164  	for _, v := range benchTasks {
   165  		b.Run("EnqueueOnly/"+v.name, func(b *testing.B) {
   166  			q := v.New()
   167  			reportalloc(b)
   168  			b.ResetTimer()
   169  			b.RunParallel(func(pb *testing.PB) {
   170  				for pb.Next() {
   171  					q.Enqueue(uint64(fastrand.Uint32()))
   172  				}
   173  			})
   174  		})
   175  	}
   176  }
   177  
   178  func benchDequeueOnlyEmpty(b *testing.B, benchTasks []benchTask) {
   179  	for _, v := range benchTasks {
   180  		b.Run("DequeueOnlyEmpty/"+v.name, func(b *testing.B) {
   181  			q := v.New()
   182  			reportalloc(b)
   183  			b.ResetTimer()
   184  			b.RunParallel(func(pb *testing.PB) {
   185  				for pb.Next() {
   186  					q.Dequeue()
   187  				}
   188  			})
   189  		})
   190  	}
   191  }