compare atomic and mutex performance for incrementing/storing one variable (#1757)
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
|
// +build go1.7
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Copyright 2017 gRPC authors.
|
* Copyright 2017 gRPC authors.
|
||||||
@ -21,9 +23,12 @@
|
|||||||
package primitives_test
|
package primitives_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkSelectClosed(b *testing.B) {
|
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 := atomic.Value{}
|
||||||
c.Store(0)
|
c.Store(0)
|
||||||
x := 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) {
|
func BenchmarkMutex(b *testing.B) {
|
||||||
c := sync.Mutex{}
|
c := sync.Mutex{}
|
||||||
x := 0
|
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{}
|
type myFooer struct{}
|
||||||
|
|
||||||
func (myFooer) Foo() {}
|
func (myFooer) Foo() {}
|
||||||
|
Reference in New Issue
Block a user