/* * * 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") } }