github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/benchmark/primitives/primitives_test.go (about)

     1  /*
     2   *
     3   * Copyright 2017 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  // Package primitives_test contains benchmarks for various synchronization primitives
    20  // available in Go.
    21  package primitives_test
    22  
    23  import (
    24  	"fmt"
    25  	"sync"
    26  	"sync/atomic"
    27  	"testing"
    28  	"time"
    29  	"unsafe"
    30  )
    31  
    32  func BenchmarkSelectClosed(b *testing.B) {
    33  	c := make(chan struct{})
    34  	close(c)
    35  	x := 0
    36  	b.ResetTimer()
    37  	for i := 0; i < b.N; i++ {
    38  		select {
    39  		case <-c:
    40  			x++
    41  		default:
    42  		}
    43  	}
    44  	b.StopTimer()
    45  	if x != b.N {
    46  		b.Fatal("error")
    47  	}
    48  }
    49  
    50  func BenchmarkSelectOpen(b *testing.B) {
    51  	c := make(chan struct{})
    52  	x := 0
    53  	b.ResetTimer()
    54  	for i := 0; i < b.N; i++ {
    55  		select {
    56  		case <-c:
    57  		default:
    58  			x++
    59  		}
    60  	}
    61  	b.StopTimer()
    62  	if x != b.N {
    63  		b.Fatal("error")
    64  	}
    65  }
    66  
    67  func BenchmarkAtomicBool(b *testing.B) {
    68  	c := int32(0)
    69  	x := 0
    70  	b.ResetTimer()
    71  	for i := 0; i < b.N; i++ {
    72  		if atomic.LoadInt32(&c) == 0 {
    73  			x++
    74  		}
    75  	}
    76  	b.StopTimer()
    77  	if x != b.N {
    78  		b.Fatal("error")
    79  	}
    80  }
    81  
    82  func BenchmarkAtomicValueLoad(b *testing.B) {
    83  	c := atomic.Value{}
    84  	c.Store(0)
    85  	x := 0
    86  	b.ResetTimer()
    87  	for i := 0; i < b.N; i++ {
    88  		if c.Load().(int) == 0 {
    89  			x++
    90  		}
    91  	}
    92  	b.StopTimer()
    93  	if x != b.N {
    94  		b.Fatal("error")
    95  	}
    96  }
    97  
    98  func BenchmarkAtomicValueStore(b *testing.B) {
    99  	c := atomic.Value{}
   100  	v := 123
   101  	b.ResetTimer()
   102  	for i := 0; i < b.N; i++ {
   103  		c.Store(v)
   104  	}
   105  	b.StopTimer()
   106  }
   107  
   108  func BenchmarkMutex(b *testing.B) {
   109  	c := sync.Mutex{}
   110  	x := 0
   111  	b.ResetTimer()
   112  	for i := 0; i < b.N; i++ {
   113  		c.Lock()
   114  		x++
   115  		c.Unlock()
   116  	}
   117  	b.StopTimer()
   118  	if x != b.N {
   119  		b.Fatal("error")
   120  	}
   121  }
   122  
   123  func BenchmarkRWMutex(b *testing.B) {
   124  	c := sync.RWMutex{}
   125  	x := 0
   126  	b.ResetTimer()
   127  	for i := 0; i < b.N; i++ {
   128  		c.RLock()
   129  		x++
   130  		c.RUnlock()
   131  	}
   132  	b.StopTimer()
   133  	if x != b.N {
   134  		b.Fatal("error")
   135  	}
   136  }
   137  
   138  func BenchmarkRWMutexW(b *testing.B) {
   139  	c := sync.RWMutex{}
   140  	x := 0
   141  	b.ResetTimer()
   142  	for i := 0; i < b.N; i++ {
   143  		c.Lock()
   144  		x++
   145  		c.Unlock()
   146  	}
   147  	b.StopTimer()
   148  	if x != b.N {
   149  		b.Fatal("error")
   150  	}
   151  }
   152  
   153  func BenchmarkMutexWithDefer(b *testing.B) {
   154  	c := sync.Mutex{}
   155  	x := 0
   156  	b.ResetTimer()
   157  	for i := 0; i < b.N; i++ {
   158  		func() {
   159  			c.Lock()
   160  			defer c.Unlock()
   161  			x++
   162  		}()
   163  	}
   164  	b.StopTimer()
   165  	if x != b.N {
   166  		b.Fatal("error")
   167  	}
   168  }
   169  
   170  func BenchmarkMutexWithClosureDefer(b *testing.B) {
   171  	c := sync.Mutex{}
   172  	x := 0
   173  	b.ResetTimer()
   174  	for i := 0; i < b.N; i++ {
   175  		func() {
   176  			c.Lock()
   177  			defer func() { c.Unlock() }()
   178  			x++
   179  		}()
   180  	}
   181  	b.StopTimer()
   182  	if x != b.N {
   183  		b.Fatal("error")
   184  	}
   185  }
   186  
   187  func BenchmarkMutexWithoutDefer(b *testing.B) {
   188  	c := sync.Mutex{}
   189  	x := 0
   190  	b.ResetTimer()
   191  	for i := 0; i < b.N; i++ {
   192  		func() {
   193  			c.Lock()
   194  			x++
   195  			c.Unlock()
   196  		}()
   197  	}
   198  	b.StopTimer()
   199  	if x != b.N {
   200  		b.Fatal("error")
   201  	}
   202  }
   203  
   204  func BenchmarkAtomicAddInt64(b *testing.B) {
   205  	var c int64
   206  	b.ResetTimer()
   207  	for i := 0; i < b.N; i++ {
   208  		atomic.AddInt64(&c, 1)
   209  	}
   210  	b.StopTimer()
   211  	if c != int64(b.N) {
   212  		b.Fatal("error")
   213  	}
   214  }
   215  
   216  func BenchmarkAtomicTimeValueStore(b *testing.B) {
   217  	var c atomic.Value
   218  	t := time.Now()
   219  	b.ResetTimer()
   220  	for i := 0; i < b.N; i++ {
   221  		c.Store(t)
   222  	}
   223  	b.StopTimer()
   224  }
   225  
   226  func BenchmarkAtomic16BValueStore(b *testing.B) {
   227  	var c atomic.Value
   228  	t := struct {
   229  		a int64
   230  		b int64
   231  	}{
   232  		123, 123,
   233  	}
   234  	b.ResetTimer()
   235  	for i := 0; i < b.N; i++ {
   236  		c.Store(t)
   237  	}
   238  	b.StopTimer()
   239  }
   240  
   241  func BenchmarkAtomic32BValueStore(b *testing.B) {
   242  	var c atomic.Value
   243  	t := struct {
   244  		a int64
   245  		b int64
   246  		c int64
   247  		d int64
   248  	}{
   249  		123, 123, 123, 123,
   250  	}
   251  	b.ResetTimer()
   252  	for i := 0; i < b.N; i++ {
   253  		c.Store(t)
   254  	}
   255  	b.StopTimer()
   256  }
   257  
   258  func BenchmarkAtomicPointerStore(b *testing.B) {
   259  	t := 123
   260  	var up unsafe.Pointer
   261  	b.ResetTimer()
   262  	for i := 0; i < b.N; i++ {
   263  		atomic.StorePointer(&up, unsafe.Pointer(&t))
   264  	}
   265  	b.StopTimer()
   266  }
   267  
   268  func BenchmarkAtomicTimePointerStore(b *testing.B) {
   269  	t := time.Now()
   270  	var up unsafe.Pointer
   271  	b.ResetTimer()
   272  	for i := 0; i < b.N; i++ {
   273  		atomic.StorePointer(&up, unsafe.Pointer(&t))
   274  	}
   275  	b.StopTimer()
   276  }
   277  
   278  func BenchmarkStoreContentionWithAtomic(b *testing.B) {
   279  	t := 123
   280  	var c unsafe.Pointer
   281  	b.RunParallel(func(pb *testing.PB) {
   282  		for pb.Next() {
   283  			atomic.StorePointer(&c, unsafe.Pointer(&t))
   284  		}
   285  	})
   286  }
   287  
   288  func BenchmarkStoreContentionWithMutex(b *testing.B) {
   289  	t := 123
   290  	var mu sync.Mutex
   291  	var c int
   292  
   293  	b.RunParallel(func(pb *testing.PB) {
   294  		for pb.Next() {
   295  			mu.Lock()
   296  			c = t
   297  			mu.Unlock()
   298  		}
   299  	})
   300  	_ = c
   301  }
   302  
   303  type dummyStruct struct {
   304  	a int64
   305  	b time.Time
   306  }
   307  
   308  func BenchmarkStructStoreContention(b *testing.B) {
   309  	d := dummyStruct{}
   310  	dp := unsafe.Pointer(&d)
   311  	t := time.Now()
   312  	for _, j := range []int{100000000, 10000, 0} {
   313  		for _, i := range []int{100000, 10} {
   314  			b.Run(fmt.Sprintf("CAS/%v/%v", j, i), func(b *testing.B) {
   315  				b.SetParallelism(i)
   316  				b.RunParallel(func(pb *testing.PB) {
   317  					n := &dummyStruct{
   318  						b: t,
   319  					}
   320  					for pb.Next() {
   321  						for y := 0; y < j; y++ {
   322  						}
   323  						for {
   324  							v := (*dummyStruct)(atomic.LoadPointer(&dp))
   325  							n.a = v.a + 1
   326  							if atomic.CompareAndSwapPointer(&dp, unsafe.Pointer(v), unsafe.Pointer(n)) {
   327  								n = v
   328  								break
   329  							}
   330  						}
   331  					}
   332  				})
   333  			})
   334  		}
   335  	}
   336  
   337  	var mu sync.Mutex
   338  	for _, j := range []int{100000000, 10000, 0} {
   339  		for _, i := range []int{100000, 10} {
   340  			b.Run(fmt.Sprintf("Mutex/%v/%v", j, i), func(b *testing.B) {
   341  				b.SetParallelism(i)
   342  				b.RunParallel(func(pb *testing.PB) {
   343  					for pb.Next() {
   344  						for y := 0; y < j; y++ {
   345  						}
   346  						mu.Lock()
   347  						d.a++
   348  						d.b = t
   349  						mu.Unlock()
   350  					}
   351  				})
   352  			})
   353  		}
   354  	}
   355  }
   356  
   357  type myFooer struct{}
   358  
   359  func (myFooer) Foo() {}
   360  
   361  type fooer interface {
   362  	Foo()
   363  }
   364  
   365  func BenchmarkInterfaceTypeAssertion(b *testing.B) {
   366  	// Call a separate function to avoid compiler optimizations.
   367  	runInterfaceTypeAssertion(b, myFooer{})
   368  }
   369  
   370  func runInterfaceTypeAssertion(b *testing.B, fer interface{}) {
   371  	x := 0
   372  	b.ResetTimer()
   373  	for i := 0; i < b.N; i++ {
   374  		if _, ok := fer.(fooer); ok {
   375  			x++
   376  		}
   377  	}
   378  	b.StopTimer()
   379  	if x != b.N {
   380  		b.Fatal("error")
   381  	}
   382  }
   383  
   384  func BenchmarkStructTypeAssertion(b *testing.B) {
   385  	// Call a separate function to avoid compiler optimizations.
   386  	runStructTypeAssertion(b, myFooer{})
   387  }
   388  
   389  func runStructTypeAssertion(b *testing.B, fer interface{}) {
   390  	x := 0
   391  	b.ResetTimer()
   392  	for i := 0; i < b.N; i++ {
   393  		if _, ok := fer.(myFooer); ok {
   394  			x++
   395  		}
   396  	}
   397  	b.StopTimer()
   398  	if x != b.N {
   399  		b.Fatal("error")
   400  	}
   401  }
   402  
   403  func BenchmarkWaitGroupAddDone(b *testing.B) {
   404  	wg := sync.WaitGroup{}
   405  	b.RunParallel(func(pb *testing.PB) {
   406  		i := 0
   407  		for ; pb.Next(); i++ {
   408  			wg.Add(1)
   409  		}
   410  		for ; i > 0; i-- {
   411  			wg.Done()
   412  		}
   413  	})
   414  }
   415  
   416  func BenchmarkRLockUnlock(b *testing.B) {
   417  	mu := sync.RWMutex{}
   418  	b.RunParallel(func(pb *testing.PB) {
   419  		i := 0
   420  		for ; pb.Next(); i++ {
   421  			mu.RLock()
   422  		}
   423  		for ; i > 0; i-- {
   424  			mu.RUnlock()
   425  		}
   426  	})
   427  }