summaryrefslogtreecommitdiff
path: root/src/pkg/sync/mutex_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/sync/mutex_test.go')
-rw-r--r--src/pkg/sync/mutex_test.go101
1 files changed, 82 insertions, 19 deletions
diff --git a/src/pkg/sync/mutex_test.go b/src/pkg/sync/mutex_test.go
index f5c20ca49..d5ada8567 100644
--- a/src/pkg/sync/mutex_test.go
+++ b/src/pkg/sync/mutex_test.go
@@ -9,6 +9,7 @@ package sync_test
import (
"runtime"
. "sync"
+ "sync/atomic"
"testing"
)
@@ -43,7 +44,7 @@ func BenchmarkContendedSemaphore(b *testing.B) {
s := new(uint32)
*s = 1
c := make(chan bool)
- runtime.GOMAXPROCS(2)
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
b.StartTimer()
go HammerSemaphore(s, b.N/2, c)
@@ -72,24 +73,6 @@ func TestMutex(t *testing.T) {
}
}
-func BenchmarkUncontendedMutex(b *testing.B) {
- m := new(Mutex)
- HammerMutex(m, b.N, make(chan bool, 2))
-}
-
-func BenchmarkContendedMutex(b *testing.B) {
- b.StopTimer()
- m := new(Mutex)
- c := make(chan bool)
- runtime.GOMAXPROCS(2)
- b.StartTimer()
-
- go HammerMutex(m, b.N/2, c)
- go HammerMutex(m, b.N/2, c)
- <-c
- <-c
-}
-
func TestMutexPanic(t *testing.T) {
defer func() {
if recover() == nil {
@@ -102,3 +85,83 @@ func TestMutexPanic(t *testing.T) {
mu.Unlock()
mu.Unlock()
}
+
+func BenchmarkMutexUncontended(b *testing.B) {
+ type PaddedMutex struct {
+ Mutex
+ pad [128]uint8
+ }
+ const CallsPerSched = 1000
+ procs := runtime.GOMAXPROCS(-1)
+ N := int32(b.N / CallsPerSched)
+ c := make(chan bool, procs)
+ for p := 0; p < procs; p++ {
+ go func() {
+ var mu PaddedMutex
+ for atomic.AddInt32(&N, -1) >= 0 {
+ runtime.Gosched()
+ for g := 0; g < CallsPerSched; g++ {
+ mu.Lock()
+ mu.Unlock()
+ }
+ }
+ c <- true
+ }()
+ }
+ for p := 0; p < procs; p++ {
+ <-c
+ }
+}
+
+func benchmarkMutex(b *testing.B, slack, work bool) {
+ const (
+ CallsPerSched = 1000
+ LocalWork = 100
+ GoroutineSlack = 10
+ )
+ procs := runtime.GOMAXPROCS(-1)
+ if slack {
+ procs *= GoroutineSlack
+ }
+ N := int32(b.N / CallsPerSched)
+ c := make(chan bool, procs)
+ var mu Mutex
+ for p := 0; p < procs; p++ {
+ go func() {
+ foo := 0
+ for atomic.AddInt32(&N, -1) >= 0 {
+ runtime.Gosched()
+ for g := 0; g < CallsPerSched; g++ {
+ mu.Lock()
+ mu.Unlock()
+ if work {
+ for i := 0; i < LocalWork; i++ {
+ foo *= 2
+ foo /= 2
+ }
+ }
+ }
+ }
+ c <- foo == 42
+ }()
+ }
+ for p := 0; p < procs; p++ {
+ <-c
+ }
+}
+
+func BenchmarkMutex(b *testing.B) {
+ benchmarkMutex(b, false, false)
+}
+
+func BenchmarkMutexSlack(b *testing.B) {
+ benchmarkMutex(b, true, false)
+}
+
+func BenchmarkMutexWork(b *testing.B) {
+ benchmarkMutex(b, false, true)
+}
+
+func BenchmarkMutexWorkSlack(b *testing.B) {
+ benchmarkMutex(b, true, true)
+}