github.com/songzhibin97/gkit@v1.2.13/structure/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  	"github.com/songzhibin97/gkit/internal/benchmark/linkedq"
    19  	"github.com/songzhibin97/gkit/internal/benchmark/msq"
    20  	"github.com/songzhibin97/gkit/sys/fastrand"
    21  	"sync/atomic"
    22  	"testing"
    23  )
    24  
    25  type uint64queue interface {
    26  	Enqueue(uint64) bool
    27  	Dequeue() (uint64, bool)
    28  }
    29  
    30  type benchTask struct {
    31  	name string
    32  	New  func() uint64queue
    33  }
    34  
    35  type faa int64
    36  
    37  func (data *faa) Enqueue(_ uint64) bool {
    38  	atomic.AddInt64((*int64)(data), 1)
    39  	return true
    40  }
    41  
    42  func (data *faa) Dequeue() (uint64, bool) {
    43  	atomic.AddInt64((*int64)(data), -1)
    44  	return 0, false
    45  }
    46  
    47  func BenchmarkDefault(b *testing.B) {
    48  	all := []benchTask{{
    49  		name: "LSCQ", New: func() uint64queue {
    50  			return NewUint64()
    51  		}}}
    52  	all = append(all, benchTask{
    53  		name: "LinkedQueue",
    54  		New: func() uint64queue {
    55  			return linkedq.New()
    56  		},
    57  	})
    58  	all = append(all, benchTask{
    59  		name: "MSQueue",
    60  		New: func() uint64queue {
    61  			return msq.New()
    62  		},
    63  	})
    64  	// all = append(all, benchTask{
    65  	// 	name: "FAA",
    66  	// 	New: func() uint64queue {
    67  	// 		return new(faa)
    68  	// 	},
    69  	// })
    70  	// all = append(all, benchTask{
    71  	// 	name: "channel",
    72  	// 	New: func() uint64queue {
    73  	// 		return newChannelQ(scqsize)
    74  	// 	},
    75  	// })
    76  	benchEnqueueOnly(b, all)
    77  	benchDequeueOnlyEmpty(b, all)
    78  	benchPair(b, all)
    79  	bench50Enqueue50Dequeue(b, all)
    80  	bench30Enqueue70Dequeue(b, all)
    81  	bench70Enqueue30Dequeue(b, all)
    82  }
    83  
    84  func reportalloc(b *testing.B) {
    85  	// b.SetBytes(8)
    86  	// b.ReportAllocs()
    87  }
    88  
    89  func benchPair(b *testing.B, benchTasks []benchTask) {
    90  	for _, v := range benchTasks {
    91  		b.Run("Pair/"+v.name, func(b *testing.B) {
    92  			q := v.New()
    93  			reportalloc(b)
    94  			b.ResetTimer()
    95  			b.RunParallel(func(pb *testing.PB) {
    96  				for pb.Next() {
    97  					q.Enqueue(uint64(fastrand.Uint32()))
    98  					q.Dequeue()
    99  				}
   100  			})
   101  		})
   102  	}
   103  }
   104  
   105  func bench50Enqueue50Dequeue(b *testing.B, benchTasks []benchTask) {
   106  	for _, v := range benchTasks {
   107  		b.Run("50Enqueue50Dequeue/"+v.name, func(b *testing.B) {
   108  			q := v.New()
   109  			b.ResetTimer()
   110  			reportalloc(b)
   111  			b.RunParallel(func(pb *testing.PB) {
   112  				for pb.Next() {
   113  					if fastrand.Uint32n(2) == 0 {
   114  						q.Enqueue(uint64(fastrand.Uint32()))
   115  					} else {
   116  						q.Dequeue()
   117  					}
   118  				}
   119  			})
   120  		})
   121  	}
   122  }
   123  
   124  func bench70Enqueue30Dequeue(b *testing.B, benchTasks []benchTask) {
   125  	for _, v := range benchTasks {
   126  		b.Run("70Enqueue30Dequeue/"+v.name, func(b *testing.B) {
   127  			q := v.New()
   128  			reportalloc(b)
   129  			b.ResetTimer()
   130  			b.RunParallel(func(pb *testing.PB) {
   131  				for pb.Next() {
   132  					if fastrand.Uint32n(10) > 2 {
   133  						q.Enqueue(uint64(fastrand.Uint32()))
   134  					} else {
   135  						q.Dequeue()
   136  					}
   137  				}
   138  			})
   139  		})
   140  	}
   141  }
   142  
   143  func bench30Enqueue70Dequeue(b *testing.B, benchTasks []benchTask) {
   144  	for _, v := range benchTasks {
   145  		b.Run("30Enqueue70Dequeue/"+v.name, func(b *testing.B) {
   146  			q := v.New()
   147  			reportalloc(b)
   148  			b.ResetTimer()
   149  			b.RunParallel(func(pb *testing.PB) {
   150  				for pb.Next() {
   151  					if fastrand.Uint32n(10) <= 2 {
   152  						q.Enqueue(uint64(fastrand.Uint32()))
   153  					} else {
   154  						q.Dequeue()
   155  					}
   156  				}
   157  			})
   158  		})
   159  	}
   160  }
   161  
   162  func benchEnqueueOnly(b *testing.B, benchTasks []benchTask) {
   163  	for _, v := range benchTasks {
   164  		b.Run("EnqueueOnly/"+v.name, func(b *testing.B) {
   165  			q := v.New()
   166  			reportalloc(b)
   167  			b.ResetTimer()
   168  			b.RunParallel(func(pb *testing.PB) {
   169  				for pb.Next() {
   170  					q.Enqueue(uint64(fastrand.Uint32()))
   171  				}
   172  			})
   173  		})
   174  	}
   175  }
   176  
   177  func benchDequeueOnlyEmpty(b *testing.B, benchTasks []benchTask) {
   178  	for _, v := range benchTasks {
   179  		b.Run("DequeueOnlyEmpty/"+v.name, func(b *testing.B) {
   180  			q := v.New()
   181  			reportalloc(b)
   182  			b.ResetTimer()
   183  			b.RunParallel(func(pb *testing.PB) {
   184  				for pb.Next() {
   185  					q.Dequeue()
   186  				}
   187  			})
   188  		})
   189  	}
   190  }