github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/proc_test.go (about) 1 // Copyright 2011 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 package runtime_test 6 7 import ( 8 "math" 9 "runtime" 10 "sync/atomic" 11 "testing" 12 "time" 13 ) 14 15 var stop = make(chan bool, 1) 16 17 func perpetuumMobile() { 18 select { 19 case <-stop: 20 default: 21 go perpetuumMobile() 22 } 23 } 24 25 func TestStopTheWorldDeadlock(t *testing.T) { 26 if testing.Short() { 27 t.Skip("skipping during short test") 28 } 29 maxprocs := runtime.GOMAXPROCS(3) 30 compl := make(chan bool, 2) 31 go func() { 32 for i := 0; i != 1000; i += 1 { 33 runtime.GC() 34 } 35 compl <- true 36 }() 37 go func() { 38 for i := 0; i != 1000; i += 1 { 39 runtime.GOMAXPROCS(3) 40 } 41 compl <- true 42 }() 43 go perpetuumMobile() 44 <-compl 45 <-compl 46 stop <- true 47 runtime.GOMAXPROCS(maxprocs) 48 } 49 50 func TestYieldProgress(t *testing.T) { 51 testYieldProgress(t, false) 52 } 53 54 func TestYieldLockedProgress(t *testing.T) { 55 testYieldProgress(t, true) 56 } 57 58 func testYieldProgress(t *testing.T, locked bool) { 59 c := make(chan bool) 60 cack := make(chan bool) 61 go func() { 62 if locked { 63 runtime.LockOSThread() 64 } 65 for { 66 select { 67 case <-c: 68 cack <- true 69 return 70 default: 71 runtime.Gosched() 72 } 73 } 74 }() 75 time.Sleep(10 * time.Millisecond) 76 c <- true 77 <-cack 78 } 79 80 func TestYieldLocked(t *testing.T) { 81 const N = 10 82 c := make(chan bool) 83 go func() { 84 runtime.LockOSThread() 85 for i := 0; i < N; i++ { 86 runtime.Gosched() 87 time.Sleep(time.Millisecond) 88 } 89 c <- true 90 // runtime.UnlockOSThread() is deliberately omitted 91 }() 92 <-c 93 } 94 95 func TestBlockLocked(t *testing.T) { 96 const N = 10 97 c := make(chan bool) 98 go func() { 99 runtime.LockOSThread() 100 for i := 0; i < N; i++ { 101 c <- true 102 } 103 runtime.UnlockOSThread() 104 }() 105 for i := 0; i < N; i++ { 106 <-c 107 } 108 } 109 110 func stackGrowthRecursive(i int) { 111 var pad [128]uint64 112 if i != 0 && pad[0] == 0 { 113 stackGrowthRecursive(i - 1) 114 } 115 } 116 117 func TestSchedLocalQueue(t *testing.T) { 118 runtime.TestSchedLocalQueue1() 119 } 120 121 func TestSchedLocalQueueSteal(t *testing.T) { 122 runtime.TestSchedLocalQueueSteal1() 123 } 124 125 func benchmarkStackGrowth(b *testing.B, rec int) { 126 const CallsPerSched = 1000 127 procs := runtime.GOMAXPROCS(-1) 128 N := int32(b.N / CallsPerSched) 129 c := make(chan bool, procs) 130 for p := 0; p < procs; p++ { 131 go func() { 132 for atomic.AddInt32(&N, -1) >= 0 { 133 runtime.Gosched() 134 for g := 0; g < CallsPerSched; g++ { 135 stackGrowthRecursive(rec) 136 } 137 } 138 c <- true 139 }() 140 } 141 for p := 0; p < procs; p++ { 142 <-c 143 } 144 } 145 146 func BenchmarkStackGrowth(b *testing.B) { 147 benchmarkStackGrowth(b, 10) 148 } 149 150 func BenchmarkStackGrowthDeep(b *testing.B) { 151 benchmarkStackGrowth(b, 1024) 152 } 153 154 func BenchmarkSyscall(b *testing.B) { 155 benchmarkSyscall(b, 0, 1) 156 } 157 158 func BenchmarkSyscallWork(b *testing.B) { 159 benchmarkSyscall(b, 100, 1) 160 } 161 162 func BenchmarkSyscallExcess(b *testing.B) { 163 benchmarkSyscall(b, 0, 4) 164 } 165 166 func BenchmarkSyscallExcessWork(b *testing.B) { 167 benchmarkSyscall(b, 100, 4) 168 } 169 170 func benchmarkSyscall(b *testing.B, work, excess int) { 171 const CallsPerSched = 1000 172 procs := runtime.GOMAXPROCS(-1) * excess 173 N := int32(b.N / CallsPerSched) 174 c := make(chan bool, procs) 175 for p := 0; p < procs; p++ { 176 go func() { 177 foo := 42 178 for atomic.AddInt32(&N, -1) >= 0 { 179 runtime.Gosched() 180 for g := 0; g < CallsPerSched; g++ { 181 runtime.Entersyscall() 182 for i := 0; i < work; i++ { 183 foo *= 2 184 foo /= 2 185 } 186 runtime.Exitsyscall() 187 } 188 } 189 c <- foo == 42 190 }() 191 } 192 for p := 0; p < procs; p++ { 193 <-c 194 } 195 } 196 197 func BenchmarkCreateGoroutines(b *testing.B) { 198 benchmarkCreateGoroutines(b, 1) 199 } 200 201 func BenchmarkCreateGoroutinesParallel(b *testing.B) { 202 benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1)) 203 } 204 205 func benchmarkCreateGoroutines(b *testing.B, procs int) { 206 c := make(chan bool) 207 var f func(n int) 208 f = func(n int) { 209 if n == 0 { 210 c <- true 211 return 212 } 213 go f(n - 1) 214 } 215 for i := 0; i < procs; i++ { 216 go f(b.N / procs) 217 } 218 for i := 0; i < procs; i++ { 219 <-c 220 } 221 } 222 223 type Matrix [][]float64 224 225 func BenchmarkMatmult(b *testing.B) { 226 b.StopTimer() 227 // matmult is O(N**3) but testing expects O(b.N), 228 // so we need to take cube root of b.N 229 n := int(math.Cbrt(float64(b.N))) + 1 230 A := makeMatrix(n) 231 B := makeMatrix(n) 232 C := makeMatrix(n) 233 b.StartTimer() 234 matmult(nil, A, B, C, 0, n, 0, n, 0, n, 8) 235 } 236 237 func makeMatrix(n int) Matrix { 238 m := make(Matrix, n) 239 for i := 0; i < n; i++ { 240 m[i] = make([]float64, n) 241 for j := 0; j < n; j++ { 242 m[i][j] = float64(i*n + j) 243 } 244 } 245 return m 246 } 247 248 func matmult(done chan<- struct{}, A, B, C Matrix, i0, i1, j0, j1, k0, k1, threshold int) { 249 di := i1 - i0 250 dj := j1 - j0 251 dk := k1 - k0 252 if di >= dj && di >= dk && di >= threshold { 253 // divide in two by y axis 254 mi := i0 + di/2 255 done1 := make(chan struct{}, 1) 256 go matmult(done1, A, B, C, i0, mi, j0, j1, k0, k1, threshold) 257 matmult(nil, A, B, C, mi, i1, j0, j1, k0, k1, threshold) 258 <-done1 259 } else if dj >= dk && dj >= threshold { 260 // divide in two by x axis 261 mj := j0 + dj/2 262 done1 := make(chan struct{}, 1) 263 go matmult(done1, A, B, C, i0, i1, j0, mj, k0, k1, threshold) 264 matmult(nil, A, B, C, i0, i1, mj, j1, k0, k1, threshold) 265 <-done1 266 } else if dk >= threshold { 267 // divide in two by "k" axis 268 // deliberately not parallel because of data races 269 mk := k0 + dk/2 270 matmult(nil, A, B, C, i0, i1, j0, j1, k0, mk, threshold) 271 matmult(nil, A, B, C, i0, i1, j0, j1, mk, k1, threshold) 272 } else { 273 // the matrices are small enough, compute directly 274 for i := i0; i < i1; i++ { 275 for j := j0; j < j1; j++ { 276 for k := k0; k < k1; k++ { 277 C[i][j] += A[i][k] * B[k][j] 278 } 279 } 280 } 281 } 282 if done != nil { 283 done <- struct{}{} 284 } 285 }