123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- /*
- *
- * Copyright 2017 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- // Package primitives_test contains benchmarks for various synchronization primitives
- // available in Go.
- package primitives_test
- import (
- "fmt"
- "sync"
- "sync/atomic"
- "testing"
- "time"
- "unsafe"
- )
- func BenchmarkSelectClosed(b *testing.B) {
- c := make(chan struct{})
- close(c)
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- select {
- case <-c:
- x++
- default:
- }
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkSelectOpen(b *testing.B) {
- c := make(chan struct{})
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- select {
- case <-c:
- default:
- x++
- }
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkAtomicBool(b *testing.B) {
- c := int32(0)
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if atomic.LoadInt32(&c) == 0 {
- x++
- }
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkAtomicValueLoad(b *testing.B) {
- c := atomic.Value{}
- c.Store(0)
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if c.Load().(int) == 0 {
- x++
- }
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkAtomicValueStore(b *testing.B) {
- c := atomic.Value{}
- v := 123
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- c.Store(v)
- }
- b.StopTimer()
- }
- func BenchmarkMutex(b *testing.B) {
- c := sync.Mutex{}
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- c.Lock()
- x++
- c.Unlock()
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkRWMutex(b *testing.B) {
- c := sync.RWMutex{}
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- c.RLock()
- x++
- c.RUnlock()
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkRWMutexW(b *testing.B) {
- c := sync.RWMutex{}
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- c.Lock()
- x++
- c.Unlock()
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkMutexWithDefer(b *testing.B) {
- c := sync.Mutex{}
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- func() {
- c.Lock()
- defer c.Unlock()
- x++
- }()
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkMutexWithClosureDefer(b *testing.B) {
- c := sync.Mutex{}
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- func() {
- c.Lock()
- defer func() { c.Unlock() }()
- x++
- }()
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkMutexWithoutDefer(b *testing.B) {
- c := sync.Mutex{}
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- func() {
- c.Lock()
- x++
- c.Unlock()
- }()
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkAtomicAddInt64(b *testing.B) {
- var c int64
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- atomic.AddInt64(&c, 1)
- }
- b.StopTimer()
- if c != int64(b.N) {
- b.Fatal("error")
- }
- }
- func BenchmarkAtomicTimeValueStore(b *testing.B) {
- var c atomic.Value
- t := time.Now()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- c.Store(t)
- }
- b.StopTimer()
- }
- func BenchmarkAtomic16BValueStore(b *testing.B) {
- var c atomic.Value
- t := struct {
- a int64
- b int64
- }{
- 123, 123,
- }
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- c.Store(t)
- }
- b.StopTimer()
- }
- func BenchmarkAtomic32BValueStore(b *testing.B) {
- var c atomic.Value
- t := struct {
- a int64
- b int64
- c int64
- d int64
- }{
- 123, 123, 123, 123,
- }
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- c.Store(t)
- }
- b.StopTimer()
- }
- func BenchmarkAtomicPointerStore(b *testing.B) {
- t := 123
- var up unsafe.Pointer
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- atomic.StorePointer(&up, unsafe.Pointer(&t))
- }
- b.StopTimer()
- }
- func BenchmarkAtomicTimePointerStore(b *testing.B) {
- t := time.Now()
- var up unsafe.Pointer
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- atomic.StorePointer(&up, unsafe.Pointer(&t))
- }
- b.StopTimer()
- }
- func BenchmarkStoreContentionWithAtomic(b *testing.B) {
- t := 123
- var c unsafe.Pointer
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- atomic.StorePointer(&c, unsafe.Pointer(&t))
- }
- })
- }
- func BenchmarkStoreContentionWithMutex(b *testing.B) {
- t := 123
- var mu sync.Mutex
- var c int
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- mu.Lock()
- c = t
- mu.Unlock()
- }
- })
- _ = c
- }
- type dummyStruct struct {
- a int64
- b time.Time
- }
- func BenchmarkStructStoreContention(b *testing.B) {
- d := dummyStruct{}
- dp := unsafe.Pointer(&d)
- t := time.Now()
- for _, j := range []int{100000000, 10000, 0} {
- for _, i := range []int{100000, 10} {
- b.Run(fmt.Sprintf("CAS/%v/%v", j, i), func(b *testing.B) {
- b.SetParallelism(i)
- b.RunParallel(func(pb *testing.PB) {
- n := &dummyStruct{
- b: t,
- }
- for pb.Next() {
- for y := 0; y < j; y++ {
- }
- for {
- v := (*dummyStruct)(atomic.LoadPointer(&dp))
- n.a = v.a + 1
- if atomic.CompareAndSwapPointer(&dp, unsafe.Pointer(v), unsafe.Pointer(n)) {
- n = v
- break
- }
- }
- }
- })
- })
- }
- }
- var mu sync.Mutex
- for _, j := range []int{100000000, 10000, 0} {
- for _, i := range []int{100000, 10} {
- b.Run(fmt.Sprintf("Mutex/%v/%v", j, i), func(b *testing.B) {
- b.SetParallelism(i)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for y := 0; y < j; y++ {
- }
- mu.Lock()
- d.a++
- d.b = t
- mu.Unlock()
- }
- })
- })
- }
- }
- }
- type myFooer struct{}
- func (myFooer) Foo() {}
- type fooer interface {
- Foo()
- }
- func BenchmarkInterfaceTypeAssertion(b *testing.B) {
- // Call a separate function to avoid compiler optimizations.
- runInterfaceTypeAssertion(b, myFooer{})
- }
- func runInterfaceTypeAssertion(b *testing.B, fer interface{}) {
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if _, ok := fer.(fooer); ok {
- x++
- }
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
- func BenchmarkStructTypeAssertion(b *testing.B) {
- // Call a separate function to avoid compiler optimizations.
- runStructTypeAssertion(b, myFooer{})
- }
- func runStructTypeAssertion(b *testing.B, fer interface{}) {
- x := 0
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if _, ok := fer.(myFooer); ok {
- x++
- }
- }
- b.StopTimer()
- if x != b.N {
- b.Fatal("error")
- }
- }
|