github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/sync/mutex_test.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // GOMAXPROCS=10 go test
     6  
     7  package sync_test
     8  
     9  import (
    10  	"runtime"
    11  	. "sync"
    12  	"sync/atomic"
    13  	"testing"
    14  )
    15  
    16  func HammerSemaphore(s *uint32, loops int, cdone chan bool) {
    17  	for i := 0; i < loops; i++ {
    18  		Runtime_Semacquire(s)
    19  		Runtime_Semrelease(s)
    20  	}
    21  	cdone <- true
    22  }
    23  
    24  func TestSemaphore(t *testing.T) {
    25  	s := new(uint32)
    26  	*s = 1
    27  	c := make(chan bool)
    28  	for i := 0; i < 10; i++ {
    29  		go HammerSemaphore(s, 1000, c)
    30  	}
    31  	for i := 0; i < 10; i++ {
    32  		<-c
    33  	}
    34  }
    35  
    36  func BenchmarkUncontendedSemaphore(b *testing.B) {
    37  	s := new(uint32)
    38  	*s = 1
    39  	HammerSemaphore(s, b.N, make(chan bool, 2))
    40  }
    41  
    42  func BenchmarkContendedSemaphore(b *testing.B) {
    43  	b.StopTimer()
    44  	s := new(uint32)
    45  	*s = 1
    46  	c := make(chan bool)
    47  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
    48  	b.StartTimer()
    49  
    50  	go HammerSemaphore(s, b.N/2, c)
    51  	go HammerSemaphore(s, b.N/2, c)
    52  	<-c
    53  	<-c
    54  }
    55  
    56  func HammerMutex(m *Mutex, loops int, cdone chan bool) {
    57  	for i := 0; i < loops; i++ {
    58  		m.Lock()
    59  		m.Unlock()
    60  	}
    61  	cdone <- true
    62  }
    63  
    64  func TestMutex(t *testing.T) {
    65  	m := new(Mutex)
    66  	c := make(chan bool)
    67  	for i := 0; i < 10; i++ {
    68  		go HammerMutex(m, 1000, c)
    69  	}
    70  	for i := 0; i < 10; i++ {
    71  		<-c
    72  	}
    73  }
    74  
    75  func TestMutexPanic(t *testing.T) {
    76  	defer func() {
    77  		if recover() == nil {
    78  			t.Fatalf("unlock of unlocked mutex did not panic")
    79  		}
    80  	}()
    81  
    82  	var mu Mutex
    83  	mu.Lock()
    84  	mu.Unlock()
    85  	mu.Unlock()
    86  }
    87  
    88  func BenchmarkMutexUncontended(b *testing.B) {
    89  	type PaddedMutex struct {
    90  		Mutex
    91  		pad [128]uint8
    92  	}
    93  	const CallsPerSched = 1000
    94  	procs := runtime.GOMAXPROCS(-1)
    95  	N := int32(b.N / CallsPerSched)
    96  	c := make(chan bool, procs)
    97  	for p := 0; p < procs; p++ {
    98  		go func() {
    99  			var mu PaddedMutex
   100  			for atomic.AddInt32(&N, -1) >= 0 {
   101  				runtime.Gosched()
   102  				for g := 0; g < CallsPerSched; g++ {
   103  					mu.Lock()
   104  					mu.Unlock()
   105  				}
   106  			}
   107  			c <- true
   108  		}()
   109  	}
   110  	for p := 0; p < procs; p++ {
   111  		<-c
   112  	}
   113  }
   114  
   115  func benchmarkMutex(b *testing.B, slack, work bool) {
   116  	const (
   117  		CallsPerSched  = 1000
   118  		LocalWork      = 100
   119  		GoroutineSlack = 10
   120  	)
   121  	procs := runtime.GOMAXPROCS(-1)
   122  	if slack {
   123  		procs *= GoroutineSlack
   124  	}
   125  	N := int32(b.N / CallsPerSched)
   126  	c := make(chan bool, procs)
   127  	var mu Mutex
   128  	for p := 0; p < procs; p++ {
   129  		go func() {
   130  			foo := 0
   131  			for atomic.AddInt32(&N, -1) >= 0 {
   132  				runtime.Gosched()
   133  				for g := 0; g < CallsPerSched; g++ {
   134  					mu.Lock()
   135  					mu.Unlock()
   136  					if work {
   137  						for i := 0; i < LocalWork; i++ {
   138  							foo *= 2
   139  							foo /= 2
   140  						}
   141  					}
   142  				}
   143  			}
   144  			c <- foo == 42
   145  		}()
   146  	}
   147  	for p := 0; p < procs; p++ {
   148  		<-c
   149  	}
   150  }
   151  
   152  func BenchmarkMutex(b *testing.B) {
   153  	benchmarkMutex(b, false, false)
   154  }
   155  
   156  func BenchmarkMutexSlack(b *testing.B) {
   157  	benchmarkMutex(b, true, false)
   158  }
   159  
   160  func BenchmarkMutexWork(b *testing.B) {
   161  	benchmarkMutex(b, false, true)
   162  }
   163  
   164  func BenchmarkMutexWorkSlack(b *testing.B) {
   165  	benchmarkMutex(b, true, true)
   166  }