blob: 59355590d58780e4fbc5fe3846640a62d7d6226f [file] [log] [blame]
/*
*
* 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")
}
}