github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/src/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  	"testing"
    13  )
    14  
    15  func HammerSemaphore(s *uint32, loops int, cdone chan bool) {
    16  	for i := 0; i < loops; i++ {
    17  		Runtime_Semacquire(s)
    18  		Runtime_Semrelease(s)
    19  	}
    20  	cdone <- true
    21  }
    22  
    23  func TestSemaphore(t *testing.T) {
    24  	s := new(uint32)
    25  	*s = 1
    26  	c := make(chan bool)
    27  	for i := 0; i < 10; i++ {
    28  		go HammerSemaphore(s, 1000, c)
    29  	}
    30  	for i := 0; i < 10; i++ {
    31  		<-c
    32  	}
    33  }
    34  
    35  func BenchmarkUncontendedSemaphore(b *testing.B) {
    36  	s := new(uint32)
    37  	*s = 1
    38  	HammerSemaphore(s, b.N, make(chan bool, 2))
    39  }
    40  
    41  func BenchmarkContendedSemaphore(b *testing.B) {
    42  	b.StopTimer()
    43  	s := new(uint32)
    44  	*s = 1
    45  	c := make(chan bool)
    46  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
    47  	b.StartTimer()
    48  
    49  	go HammerSemaphore(s, b.N/2, c)
    50  	go HammerSemaphore(s, b.N/2, c)
    51  	<-c
    52  	<-c
    53  }
    54  
    55  func HammerMutex(m *Mutex, loops int, cdone chan bool) {
    56  	for i := 0; i < loops; i++ {
    57  		m.Lock()
    58  		m.Unlock()
    59  	}
    60  	cdone <- true
    61  }
    62  
    63  func TestMutex(t *testing.T) {
    64  	m := new(Mutex)
    65  	c := make(chan bool)
    66  	for i := 0; i < 10; i++ {
    67  		go HammerMutex(m, 1000, c)
    68  	}
    69  	for i := 0; i < 10; i++ {
    70  		<-c
    71  	}
    72  }
    73  
    74  func TestMutexPanic(t *testing.T) {
    75  	defer func() {
    76  		if recover() == nil {
    77  			t.Fatalf("unlock of unlocked mutex did not panic")
    78  		}
    79  	}()
    80  
    81  	var mu Mutex
    82  	mu.Lock()
    83  	mu.Unlock()
    84  	mu.Unlock()
    85  }
    86  
    87  func BenchmarkMutexUncontended(b *testing.B) {
    88  	type PaddedMutex struct {
    89  		Mutex
    90  		pad [128]uint8
    91  	}
    92  	b.RunParallel(func(pb *testing.PB) {
    93  		var mu PaddedMutex
    94  		for pb.Next() {
    95  			mu.Lock()
    96  			mu.Unlock()
    97  		}
    98  	})
    99  }
   100  
   101  func benchmarkMutex(b *testing.B, slack, work bool) {
   102  	var mu Mutex
   103  	if slack {
   104  		b.SetParallelism(10)
   105  	}
   106  	b.RunParallel(func(pb *testing.PB) {
   107  		foo := 0
   108  		for pb.Next() {
   109  			mu.Lock()
   110  			mu.Unlock()
   111  			if work {
   112  				for i := 0; i < 100; i++ {
   113  					foo *= 2
   114  					foo /= 2
   115  				}
   116  			}
   117  		}
   118  		_ = foo
   119  	})
   120  }
   121  
   122  func BenchmarkMutex(b *testing.B) {
   123  	benchmarkMutex(b, false, false)
   124  }
   125  
   126  func BenchmarkMutexSlack(b *testing.B) {
   127  	benchmarkMutex(b, true, false)
   128  }
   129  
   130  func BenchmarkMutexWork(b *testing.B) {
   131  	benchmarkMutex(b, false, true)
   132  }
   133  
   134  func BenchmarkMutexWorkSlack(b *testing.B) {
   135  	benchmarkMutex(b, true, true)
   136  }