Source file
src/sync/rwmutex_test.go
Documentation: sync
1
2
3
4
5
6
7 package sync_test
8
9 import (
10 "fmt"
11 "runtime"
12 . "sync"
13 "sync/atomic"
14 "testing"
15 )
16
17
18
19
20 func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) {
21 m.RLock()
22 clocked <- true
23 <-cunlock
24 m.RUnlock()
25 cdone <- true
26 }
27
28 func doTestParallelReaders(numReaders, gomaxprocs int) {
29 runtime.GOMAXPROCS(gomaxprocs)
30 var m RWMutex
31 clocked := make(chan bool)
32 cunlock := make(chan bool)
33 cdone := make(chan bool)
34 for i := 0; i < numReaders; i++ {
35 go parallelReader(&m, clocked, cunlock, cdone)
36 }
37
38 for i := 0; i < numReaders; i++ {
39 <-clocked
40 }
41 for i := 0; i < numReaders; i++ {
42 cunlock <- true
43 }
44
45 for i := 0; i < numReaders; i++ {
46 <-cdone
47 }
48 }
49
50 func TestParallelReaders(t *testing.T) {
51 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1))
52 doTestParallelReaders(1, 4)
53 doTestParallelReaders(3, 4)
54 doTestParallelReaders(4, 2)
55 }
56
57 func reader(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
58 for i := 0; i < num_iterations; i++ {
59 rwm.RLock()
60 n := atomic.AddInt32(activity, 1)
61 if n < 1 || n >= 10000 {
62 rwm.RUnlock()
63 panic(fmt.Sprintf("wlock(%d)\n", n))
64 }
65 for i := 0; i < 100; i++ {
66 }
67 atomic.AddInt32(activity, -1)
68 rwm.RUnlock()
69 }
70 cdone <- true
71 }
72
73 func writer(rwm *RWMutex, num_iterations int, activity *int32, cdone chan bool) {
74 for i := 0; i < num_iterations; i++ {
75 rwm.Lock()
76 n := atomic.AddInt32(activity, 10000)
77 if n != 10000 {
78 rwm.Unlock()
79 panic(fmt.Sprintf("wlock(%d)\n", n))
80 }
81 for i := 0; i < 100; i++ {
82 }
83 atomic.AddInt32(activity, -10000)
84 rwm.Unlock()
85 }
86 cdone <- true
87 }
88
89 func HammerRWMutex(gomaxprocs, numReaders, num_iterations int) {
90 runtime.GOMAXPROCS(gomaxprocs)
91
92 var activity int32
93 var rwm RWMutex
94 cdone := make(chan bool)
95 go writer(&rwm, num_iterations, &activity, cdone)
96 var i int
97 for i = 0; i < numReaders/2; i++ {
98 go reader(&rwm, num_iterations, &activity, cdone)
99 }
100 go writer(&rwm, num_iterations, &activity, cdone)
101 for ; i < numReaders; i++ {
102 go reader(&rwm, num_iterations, &activity, cdone)
103 }
104
105 for i := 0; i < 2+numReaders; i++ {
106 <-cdone
107 }
108 }
109
110 func TestRWMutex(t *testing.T) {
111 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(-1))
112 n := 1000
113 if testing.Short() {
114 n = 5
115 }
116 HammerRWMutex(1, 1, n)
117 HammerRWMutex(1, 3, n)
118 HammerRWMutex(1, 10, n)
119 HammerRWMutex(4, 1, n)
120 HammerRWMutex(4, 3, n)
121 HammerRWMutex(4, 10, n)
122 HammerRWMutex(10, 1, n)
123 HammerRWMutex(10, 3, n)
124 HammerRWMutex(10, 10, n)
125 HammerRWMutex(10, 5, n)
126 }
127
128 func TestRLocker(t *testing.T) {
129 var wl RWMutex
130 var rl Locker
131 wlocked := make(chan bool, 1)
132 rlocked := make(chan bool, 1)
133 rl = wl.RLocker()
134 n := 10
135 go func() {
136 for i := 0; i < n; i++ {
137 rl.Lock()
138 rl.Lock()
139 rlocked <- true
140 wl.Lock()
141 wlocked <- true
142 }
143 }()
144 for i := 0; i < n; i++ {
145 <-rlocked
146 rl.Unlock()
147 select {
148 case <-wlocked:
149 t.Fatal("RLocker() didn't read-lock it")
150 default:
151 }
152 rl.Unlock()
153 <-wlocked
154 select {
155 case <-rlocked:
156 t.Fatal("RLocker() didn't respect the write lock")
157 default:
158 }
159 wl.Unlock()
160 }
161 }
162
163 func BenchmarkRWMutexUncontended(b *testing.B) {
164 type PaddedRWMutex struct {
165 RWMutex
166 pad [32]uint32
167 }
168 b.RunParallel(func(pb *testing.PB) {
169 var rwm PaddedRWMutex
170 for pb.Next() {
171 rwm.RLock()
172 rwm.RLock()
173 rwm.RUnlock()
174 rwm.RUnlock()
175 rwm.Lock()
176 rwm.Unlock()
177 }
178 })
179 }
180
181 func benchmarkRWMutex(b *testing.B, localWork, writeRatio int) {
182 var rwm RWMutex
183 b.RunParallel(func(pb *testing.PB) {
184 foo := 0
185 for pb.Next() {
186 foo++
187 if foo%writeRatio == 0 {
188 rwm.Lock()
189 rwm.Unlock()
190 } else {
191 rwm.RLock()
192 for i := 0; i != localWork; i += 1 {
193 foo *= 2
194 foo /= 2
195 }
196 rwm.RUnlock()
197 }
198 }
199 _ = foo
200 })
201 }
202
203 func BenchmarkRWMutexWrite100(b *testing.B) {
204 benchmarkRWMutex(b, 0, 100)
205 }
206
207 func BenchmarkRWMutexWrite10(b *testing.B) {
208 benchmarkRWMutex(b, 0, 10)
209 }
210
211 func BenchmarkRWMutexWorkWrite100(b *testing.B) {
212 benchmarkRWMutex(b, 100, 100)
213 }
214
215 func BenchmarkRWMutexWorkWrite10(b *testing.B) {
216 benchmarkRWMutex(b, 100, 10)
217 }
218
View as plain text