compare atomic and mutex performance for incrementing/storing one variable (#1757)

This commit is contained in:
lyuxuan
2018-01-02 10:46:13 -08:00
committed by GitHub
parent 65c901e458
commit 17c6e90cd5

View File

@ -1,3 +1,5 @@
// +build go1.7
/*
*
* Copyright 2017 gRPC authors.
@ -21,9 +23,12 @@
package primitives_test
import (
"fmt"
"sync"
"sync/atomic"
"testing"
"time"
"unsafe"
)
func BenchmarkSelectClosed(b *testing.B) {
@ -76,7 +81,7 @@ func BenchmarkAtomicBool(b *testing.B) {
}
}
func BenchmarkAtomicValue(b *testing.B) {
func BenchmarkAtomicValueLoad(b *testing.B) {
c := atomic.Value{}
c.Store(0)
x := 0
@ -92,6 +97,16 @@ func BenchmarkAtomicValue(b *testing.B) {
}
}
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
@ -188,6 +203,132 @@ func BenchmarkMutexWithoutDefer(b *testing.B) {
}
}
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 BenchmarkValueStoreWithContention(b *testing.B) {
t := 123
for _, n := range []int{10, 100, 1000, 10000, 100000} {
b.Run(fmt.Sprintf("Atomic/%v", n), func(b *testing.B) {
var wg sync.WaitGroup
var c atomic.Value
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
for j := 0; j < b.N; j++ {
c.Store(t)
}
wg.Done()
}()
}
wg.Wait()
})
b.Run(fmt.Sprintf("AtomicStorePointer/%v", n), func(b *testing.B) {
var wg sync.WaitGroup
var up unsafe.Pointer
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
for j := 0; j < b.N; j++ {
atomic.StorePointer(&up, unsafe.Pointer(&t))
}
wg.Done()
}()
}
wg.Wait()
})
b.Run(fmt.Sprintf("Mutex/%v", n), func(b *testing.B) {
var wg sync.WaitGroup
var c int
mu := sync.Mutex{}
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
for j := 0; j < b.N; j++ {
mu.Lock()
c = t
mu.Unlock()
}
wg.Done()
}()
}
_ = c
wg.Wait()
})
}
}
type myFooer struct{}
func (myFooer) Foo() {}