| /* |
| * |
| * 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 ( |
| "sync" |
| "sync/atomic" |
| "testing" |
| ) |
| |
| 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 BenchmarkAtomicValue(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 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") |
| } |
| } |
| |
| 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") |
| } |
| } |