diff options
Diffstat (limited to 'src/pkg/sync/mutex_test.go')
-rw-r--r-- | src/pkg/sync/mutex_test.go | 101 |
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) +} |