mutex_test.go 2.2 KB

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