Source file
src/runtime/chan_test.go
Documentation: runtime
1
2
3
4
5 package runtime_test
6
7 import (
8 "internal/testenv"
9 "math"
10 "runtime"
11 "sync"
12 "sync/atomic"
13 "testing"
14 "time"
15 )
16
17 func TestChan(t *testing.T) {
18 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
19 N := 200
20 if testing.Short() {
21 N = 20
22 }
23 for chanCap := 0; chanCap < N; chanCap++ {
24 {
25
26 c := make(chan int, chanCap)
27 recv1 := false
28 go func() {
29 _ = <-c
30 recv1 = true
31 }()
32 recv2 := false
33 go func() {
34 _, _ = <-c
35 recv2 = true
36 }()
37 time.Sleep(time.Millisecond)
38 if recv1 || recv2 {
39 t.Fatalf("chan[%d]: receive from empty chan", chanCap)
40 }
41
42 select {
43 case _ = <-c:
44 t.Fatalf("chan[%d]: receive from empty chan", chanCap)
45 default:
46 }
47 select {
48 case _, _ = <-c:
49 t.Fatalf("chan[%d]: receive from empty chan", chanCap)
50 default:
51 }
52 c <- 0
53 c <- 0
54 }
55
56 {
57
58 c := make(chan int, chanCap)
59 for i := 0; i < chanCap; i++ {
60 c <- i
61 }
62 sent := uint32(0)
63 go func() {
64 c <- 0
65 atomic.StoreUint32(&sent, 1)
66 }()
67 time.Sleep(time.Millisecond)
68 if atomic.LoadUint32(&sent) != 0 {
69 t.Fatalf("chan[%d]: send to full chan", chanCap)
70 }
71
72 select {
73 case c <- 0:
74 t.Fatalf("chan[%d]: send to full chan", chanCap)
75 default:
76 }
77 <-c
78 }
79
80 {
81
82 c := make(chan int, chanCap)
83 for i := 0; i < chanCap; i++ {
84 c <- i
85 }
86 close(c)
87 for i := 0; i < chanCap; i++ {
88 v := <-c
89 if v != i {
90 t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, i)
91 }
92 }
93 if v := <-c; v != 0 {
94 t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, 0)
95 }
96 if v, ok := <-c; v != 0 || ok {
97 t.Fatalf("chan[%d]: received %v/%v, expected %v/%v", chanCap, v, ok, 0, false)
98 }
99 }
100
101 {
102
103 c := make(chan int, chanCap)
104 done := make(chan bool)
105 go func() {
106 v, ok := <-c
107 done <- v == 0 && ok == false
108 }()
109 time.Sleep(time.Millisecond)
110 close(c)
111 if !<-done {
112 t.Fatalf("chan[%d]: received non zero from closed chan", chanCap)
113 }
114 }
115
116 {
117
118
119 c := make(chan int, chanCap)
120 go func() {
121 for i := 0; i < 100; i++ {
122 c <- i
123 }
124 }()
125 for i := 0; i < 100; i++ {
126 v := <-c
127 if v != i {
128 t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, i)
129 }
130 }
131
132
133 go func() {
134 for i := 0; i < 100; i++ {
135 c <- i
136 }
137 }()
138 for i := 0; i < 100; i++ {
139 v, ok := <-c
140 if !ok {
141 t.Fatalf("chan[%d]: receive failed, expected %v", chanCap, i)
142 }
143 if v != i {
144 t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, i)
145 }
146 }
147
148
149
150 const P = 4
151 const L = 1000
152 for p := 0; p < P; p++ {
153 go func() {
154 for i := 0; i < L; i++ {
155 c <- i
156 }
157 }()
158 }
159 done := make(chan map[int]int)
160 for p := 0; p < P; p++ {
161 go func() {
162 recv := make(map[int]int)
163 for i := 0; i < L; i++ {
164 v := <-c
165 recv[v] = recv[v] + 1
166 }
167 done <- recv
168 }()
169 }
170 recv := make(map[int]int)
171 for p := 0; p < P; p++ {
172 for k, v := range <-done {
173 recv[k] = recv[k] + v
174 }
175 }
176 if len(recv) != L {
177 t.Fatalf("chan[%d]: received %v values, expected %v", chanCap, len(recv), L)
178 }
179 for _, v := range recv {
180 if v != P {
181 t.Fatalf("chan[%d]: received %v values, expected %v", chanCap, v, P)
182 }
183 }
184 }
185
186 {
187
188 c := make(chan int, chanCap)
189 if len(c) != 0 || cap(c) != chanCap {
190 t.Fatalf("chan[%d]: bad len/cap, expect %v/%v, got %v/%v", chanCap, 0, chanCap, len(c), cap(c))
191 }
192 for i := 0; i < chanCap; i++ {
193 c <- i
194 }
195 if len(c) != chanCap || cap(c) != chanCap {
196 t.Fatalf("chan[%d]: bad len/cap, expect %v/%v, got %v/%v", chanCap, chanCap, chanCap, len(c), cap(c))
197 }
198 }
199
200 }
201 }
202
203 func TestNonblockRecvRace(t *testing.T) {
204 n := 10000
205 if testing.Short() {
206 n = 100
207 }
208 for i := 0; i < n; i++ {
209 c := make(chan int, 1)
210 c <- 1
211 go func() {
212 select {
213 case <-c:
214 default:
215 t.Error("chan is not ready")
216 }
217 }()
218 close(c)
219 <-c
220 if t.Failed() {
221 return
222 }
223 }
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238 func TestNonblockSelectRace(t *testing.T) {
239 n := 100000
240 if testing.Short() {
241 n = 1000
242 }
243 done := make(chan bool, 1)
244 for i := 0; i < n; i++ {
245 c1 := make(chan int, 1)
246 c2 := make(chan int, 1)
247 c1 <- 1
248 go func() {
249 select {
250 case <-c1:
251 case <-c2:
252 default:
253 done <- false
254 return
255 }
256 done <- true
257 }()
258 c2 <- 1
259 select {
260 case <-c1:
261 default:
262 }
263 if !<-done {
264 t.Fatal("no chan is ready")
265 }
266 }
267 }
268
269
270 func TestNonblockSelectRace2(t *testing.T) {
271 n := 100000
272 if testing.Short() {
273 n = 1000
274 }
275 done := make(chan bool, 1)
276 for i := 0; i < n; i++ {
277 c1 := make(chan int, 1)
278 c2 := make(chan int)
279 c1 <- 1
280 go func() {
281 select {
282 case <-c1:
283 case <-c2:
284 default:
285 done <- false
286 return
287 }
288 done <- true
289 }()
290 close(c2)
291 select {
292 case <-c1:
293 default:
294 }
295 if !<-done {
296 t.Fatal("no chan is ready")
297 }
298 }
299 }
300
301 func TestSelfSelect(t *testing.T) {
302
303
304 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
305 for _, chanCap := range []int{0, 10} {
306 var wg sync.WaitGroup
307 wg.Add(2)
308 c := make(chan int, chanCap)
309 for p := 0; p < 2; p++ {
310 p := p
311 go func() {
312 defer wg.Done()
313 for i := 0; i < 1000; i++ {
314 if p == 0 || i%2 == 0 {
315 select {
316 case c <- p:
317 case v := <-c:
318 if chanCap == 0 && v == p {
319 t.Errorf("self receive")
320 return
321 }
322 }
323 } else {
324 select {
325 case v := <-c:
326 if chanCap == 0 && v == p {
327 t.Errorf("self receive")
328 return
329 }
330 case c <- p:
331 }
332 }
333 }
334 }()
335 }
336 wg.Wait()
337 }
338 }
339
340 func TestSelectStress(t *testing.T) {
341 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(10))
342 var c [4]chan int
343 c[0] = make(chan int)
344 c[1] = make(chan int)
345 c[2] = make(chan int, 2)
346 c[3] = make(chan int, 3)
347 N := int(1e5)
348 if testing.Short() {
349 N /= 10
350 }
351
352
353
354
355
356
357 var wg sync.WaitGroup
358 wg.Add(10)
359 for k := 0; k < 4; k++ {
360 k := k
361 go func() {
362 for i := 0; i < N; i++ {
363 c[k] <- 0
364 }
365 wg.Done()
366 }()
367 go func() {
368 for i := 0; i < N; i++ {
369 <-c[k]
370 }
371 wg.Done()
372 }()
373 }
374 go func() {
375 var n [4]int
376 c1 := c
377 for i := 0; i < 4*N; i++ {
378 select {
379 case c1[3] <- 0:
380 n[3]++
381 if n[3] == N {
382 c1[3] = nil
383 }
384 case c1[2] <- 0:
385 n[2]++
386 if n[2] == N {
387 c1[2] = nil
388 }
389 case c1[0] <- 0:
390 n[0]++
391 if n[0] == N {
392 c1[0] = nil
393 }
394 case c1[1] <- 0:
395 n[1]++
396 if n[1] == N {
397 c1[1] = nil
398 }
399 }
400 }
401 wg.Done()
402 }()
403 go func() {
404 var n [4]int
405 c1 := c
406 for i := 0; i < 4*N; i++ {
407 select {
408 case <-c1[0]:
409 n[0]++
410 if n[0] == N {
411 c1[0] = nil
412 }
413 case <-c1[1]:
414 n[1]++
415 if n[1] == N {
416 c1[1] = nil
417 }
418 case <-c1[2]:
419 n[2]++
420 if n[2] == N {
421 c1[2] = nil
422 }
423 case <-c1[3]:
424 n[3]++
425 if n[3] == N {
426 c1[3] = nil
427 }
428 }
429 }
430 wg.Done()
431 }()
432 wg.Wait()
433 }
434
435 func TestSelectFairness(t *testing.T) {
436 const trials = 10000
437 if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" {
438 testenv.SkipFlaky(t, 22047)
439 }
440 c1 := make(chan byte, trials+1)
441 c2 := make(chan byte, trials+1)
442 for i := 0; i < trials+1; i++ {
443 c1 <- 1
444 c2 <- 2
445 }
446 c3 := make(chan byte)
447 c4 := make(chan byte)
448 out := make(chan byte)
449 done := make(chan byte)
450 var wg sync.WaitGroup
451 wg.Add(1)
452 go func() {
453 defer wg.Done()
454 for {
455 var b byte
456 select {
457 case b = <-c3:
458 case b = <-c4:
459 case b = <-c1:
460 case b = <-c2:
461 }
462 select {
463 case out <- b:
464 case <-done:
465 return
466 }
467 }
468 }()
469 cnt1, cnt2 := 0, 0
470 for i := 0; i < trials; i++ {
471 switch b := <-out; b {
472 case 1:
473 cnt1++
474 case 2:
475 cnt2++
476 default:
477 t.Fatalf("unexpected value %d on channel", b)
478 }
479 }
480
481
482
483
484 r := float64(cnt1) / trials
485 e := math.Abs(r - 0.5)
486 t.Log(cnt1, cnt2, r, e)
487 if e > 4.891676/(2*math.Sqrt(trials)) {
488 t.Errorf("unfair select: in %d trials, results were %d, %d", trials, cnt1, cnt2)
489 }
490 close(done)
491 wg.Wait()
492 }
493
494 func TestChanSendInterface(t *testing.T) {
495 type mt struct{}
496 m := &mt{}
497 c := make(chan interface{}, 1)
498 c <- m
499 select {
500 case c <- m:
501 default:
502 }
503 select {
504 case c <- m:
505 case c <- &mt{}:
506 default:
507 }
508 }
509
510 func TestPseudoRandomSend(t *testing.T) {
511 n := 100
512 for _, chanCap := range []int{0, n} {
513 c := make(chan int, chanCap)
514 l := make([]int, n)
515 var m sync.Mutex
516 m.Lock()
517 go func() {
518 for i := 0; i < n; i++ {
519 runtime.Gosched()
520 l[i] = <-c
521 }
522 m.Unlock()
523 }()
524 for i := 0; i < n; i++ {
525 select {
526 case c <- 1:
527 case c <- 0:
528 }
529 }
530 m.Lock()
531 n0 := 0
532 n1 := 0
533 for _, i := range l {
534 n0 += (i + 1) % 2
535 n1 += i
536 }
537 if n0 <= n/10 || n1 <= n/10 {
538 t.Errorf("Want pseudorandom, got %d zeros and %d ones (chan cap %d)", n0, n1, chanCap)
539 }
540 }
541 }
542
543 func TestMultiConsumer(t *testing.T) {
544 const nwork = 23
545 const niter = 271828
546
547 pn := []int{2, 3, 7, 11, 13, 17, 19, 23, 27, 31}
548
549 q := make(chan int, nwork*3)
550 r := make(chan int, nwork*3)
551
552
553 var wg sync.WaitGroup
554 for i := 0; i < nwork; i++ {
555 wg.Add(1)
556 go func(w int) {
557 for v := range q {
558
559 if pn[w%len(pn)] == v {
560 runtime.Gosched()
561 }
562 r <- v
563 }
564 wg.Done()
565 }(i)
566 }
567
568
569 expect := 0
570 go func() {
571 for i := 0; i < niter; i++ {
572 v := pn[i%len(pn)]
573 expect += v
574 q <- v
575 }
576 close(q)
577 wg.Wait()
578 close(r)
579 }()
580
581
582 n := 0
583 s := 0
584 for v := range r {
585 n++
586 s += v
587 }
588 if n != niter || s != expect {
589 t.Errorf("Expected sum %d (got %d) from %d iter (saw %d)",
590 expect, s, niter, n)
591 }
592 }
593
594 func TestShrinkStackDuringBlockedSend(t *testing.T) {
595
596
597
598
599 const n = 10
600 c := make(chan int)
601 done := make(chan struct{})
602
603 go func() {
604 for i := 0; i < n; i++ {
605 c <- i
606
607 stackGrowthRecursive(20)
608 }
609 done <- struct{}{}
610 }()
611
612 for i := 0; i < n; i++ {
613 x := <-c
614 if x != i {
615 t.Errorf("bad channel read: want %d, got %d", i, x)
616 }
617
618
619 time.Sleep(1 * time.Millisecond)
620
621 runtime.GC()
622 }
623 <-done
624 }
625
626 func TestNoShrinkStackWhileParking(t *testing.T) {
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644 const n = 10
645 send := func(c chan<- int, done chan struct{}) {
646 for i := 0; i < n; i++ {
647 c <- i
648
649
650
651
652
653
654 stackGrowthRecursive(20)
655 }
656 done <- struct{}{}
657 }
658 recv := func(c <-chan int, done chan struct{}) {
659 for i := 0; i < n; i++ {
660
661
662 time.Sleep(10 * time.Microsecond)
663 <-c
664 }
665 done <- struct{}{}
666 }
667 for i := 0; i < n*20; i++ {
668 c := make(chan int)
669 done := make(chan struct{})
670 go recv(c, done)
671 go send(c, done)
672
673
674
675 time.Sleep(50 * time.Microsecond)
676 runtime.GC()
677 <-done
678 <-done
679 }
680 }
681
682 func TestSelectDuplicateChannel(t *testing.T) {
683
684
685 c := make(chan int)
686 d := make(chan int)
687 e := make(chan int)
688
689
690 go func() {
691 select {
692 case <-c:
693 case <-c:
694 case <-d:
695 }
696 e <- 9
697 }()
698 time.Sleep(time.Millisecond)
699
700
701 go func() {
702 <-c
703 }()
704 time.Sleep(time.Millisecond)
705
706 d <- 7
707 <-e
708 c <- 8
709 }
710
711 func TestSelectStackAdjust(t *testing.T) {
712
713
714 c := make(chan *int)
715 d := make(chan *int)
716 ready1 := make(chan bool)
717 ready2 := make(chan bool)
718
719 f := func(ready chan bool, dup bool) {
720
721 stackGrowthRecursive((10 << 10) / (128 * 8))
722
723
724 ready <- true
725
726 val := 42
727 var cx *int
728 cx = &val
729
730 var c2 chan *int
731 var d2 chan *int
732 if dup {
733 c2 = c
734 d2 = d
735 }
736
737
738 select {
739 case cx = <-c:
740 case <-c2:
741 case <-d:
742 case <-d2:
743 }
744
745
746 if cx != &val {
747 t.Error("cx no longer points to val")
748 } else if val != 42 {
749 t.Error("val changed")
750 } else {
751 *cx = 43
752 if val != 43 {
753 t.Error("changing *cx failed to change val")
754 }
755 }
756 ready <- true
757 }
758
759 go f(ready1, false)
760 go f(ready2, true)
761
762
763 <-ready1
764 <-ready2
765 time.Sleep(10 * time.Millisecond)
766
767
768 runtime.GC()
769
770
771 close(d)
772 <-ready1
773 <-ready2
774 }
775
776 type struct0 struct{}
777
778 func BenchmarkMakeChan(b *testing.B) {
779 b.Run("Byte", func(b *testing.B) {
780 var x chan byte
781 for i := 0; i < b.N; i++ {
782 x = make(chan byte, 8)
783 }
784 close(x)
785 })
786 b.Run("Int", func(b *testing.B) {
787 var x chan int
788 for i := 0; i < b.N; i++ {
789 x = make(chan int, 8)
790 }
791 close(x)
792 })
793 b.Run("Ptr", func(b *testing.B) {
794 var x chan *byte
795 for i := 0; i < b.N; i++ {
796 x = make(chan *byte, 8)
797 }
798 close(x)
799 })
800 b.Run("Struct", func(b *testing.B) {
801 b.Run("0", func(b *testing.B) {
802 var x chan struct0
803 for i := 0; i < b.N; i++ {
804 x = make(chan struct0, 8)
805 }
806 close(x)
807 })
808 b.Run("32", func(b *testing.B) {
809 var x chan struct32
810 for i := 0; i < b.N; i++ {
811 x = make(chan struct32, 8)
812 }
813 close(x)
814 })
815 b.Run("40", func(b *testing.B) {
816 var x chan struct40
817 for i := 0; i < b.N; i++ {
818 x = make(chan struct40, 8)
819 }
820 close(x)
821 })
822 })
823 }
824
825 func BenchmarkChanNonblocking(b *testing.B) {
826 myc := make(chan int)
827 b.RunParallel(func(pb *testing.PB) {
828 for pb.Next() {
829 select {
830 case <-myc:
831 default:
832 }
833 }
834 })
835 }
836
837 func BenchmarkSelectUncontended(b *testing.B) {
838 b.RunParallel(func(pb *testing.PB) {
839 myc1 := make(chan int, 1)
840 myc2 := make(chan int, 1)
841 myc1 <- 0
842 for pb.Next() {
843 select {
844 case <-myc1:
845 myc2 <- 0
846 case <-myc2:
847 myc1 <- 0
848 }
849 }
850 })
851 }
852
853 func BenchmarkSelectSyncContended(b *testing.B) {
854 myc1 := make(chan int)
855 myc2 := make(chan int)
856 myc3 := make(chan int)
857 done := make(chan int)
858 b.RunParallel(func(pb *testing.PB) {
859 go func() {
860 for {
861 select {
862 case myc1 <- 0:
863 case myc2 <- 0:
864 case myc3 <- 0:
865 case <-done:
866 return
867 }
868 }
869 }()
870 for pb.Next() {
871 select {
872 case <-myc1:
873 case <-myc2:
874 case <-myc3:
875 }
876 }
877 })
878 close(done)
879 }
880
881 func BenchmarkSelectAsyncContended(b *testing.B) {
882 procs := runtime.GOMAXPROCS(0)
883 myc1 := make(chan int, procs)
884 myc2 := make(chan int, procs)
885 b.RunParallel(func(pb *testing.PB) {
886 myc1 <- 0
887 for pb.Next() {
888 select {
889 case <-myc1:
890 myc2 <- 0
891 case <-myc2:
892 myc1 <- 0
893 }
894 }
895 })
896 }
897
898 func BenchmarkSelectNonblock(b *testing.B) {
899 myc1 := make(chan int)
900 myc2 := make(chan int)
901 myc3 := make(chan int, 1)
902 myc4 := make(chan int, 1)
903 b.RunParallel(func(pb *testing.PB) {
904 for pb.Next() {
905 select {
906 case <-myc1:
907 default:
908 }
909 select {
910 case myc2 <- 0:
911 default:
912 }
913 select {
914 case <-myc3:
915 default:
916 }
917 select {
918 case myc4 <- 0:
919 default:
920 }
921 }
922 })
923 }
924
925 func BenchmarkChanUncontended(b *testing.B) {
926 const C = 100
927 b.RunParallel(func(pb *testing.PB) {
928 myc := make(chan int, C)
929 for pb.Next() {
930 for i := 0; i < C; i++ {
931 myc <- 0
932 }
933 for i := 0; i < C; i++ {
934 <-myc
935 }
936 }
937 })
938 }
939
940 func BenchmarkChanContended(b *testing.B) {
941 const C = 100
942 myc := make(chan int, C*runtime.GOMAXPROCS(0))
943 b.RunParallel(func(pb *testing.PB) {
944 for pb.Next() {
945 for i := 0; i < C; i++ {
946 myc <- 0
947 }
948 for i := 0; i < C; i++ {
949 <-myc
950 }
951 }
952 })
953 }
954
955 func benchmarkChanSync(b *testing.B, work int) {
956 const CallsPerSched = 1000
957 procs := 2
958 N := int32(b.N / CallsPerSched / procs * procs)
959 c := make(chan bool, procs)
960 myc := make(chan int)
961 for p := 0; p < procs; p++ {
962 go func() {
963 for {
964 i := atomic.AddInt32(&N, -1)
965 if i < 0 {
966 break
967 }
968 for g := 0; g < CallsPerSched; g++ {
969 if i%2 == 0 {
970 <-myc
971 localWork(work)
972 myc <- 0
973 localWork(work)
974 } else {
975 myc <- 0
976 localWork(work)
977 <-myc
978 localWork(work)
979 }
980 }
981 }
982 c <- true
983 }()
984 }
985 for p := 0; p < procs; p++ {
986 <-c
987 }
988 }
989
990 func BenchmarkChanSync(b *testing.B) {
991 benchmarkChanSync(b, 0)
992 }
993
994 func BenchmarkChanSyncWork(b *testing.B) {
995 benchmarkChanSync(b, 1000)
996 }
997
998 func benchmarkChanProdCons(b *testing.B, chanSize, localWork int) {
999 const CallsPerSched = 1000
1000 procs := runtime.GOMAXPROCS(-1)
1001 N := int32(b.N / CallsPerSched)
1002 c := make(chan bool, 2*procs)
1003 myc := make(chan int, chanSize)
1004 for p := 0; p < procs; p++ {
1005 go func() {
1006 foo := 0
1007 for atomic.AddInt32(&N, -1) >= 0 {
1008 for g := 0; g < CallsPerSched; g++ {
1009 for i := 0; i < localWork; i++ {
1010 foo *= 2
1011 foo /= 2
1012 }
1013 myc <- 1
1014 }
1015 }
1016 myc <- 0
1017 c <- foo == 42
1018 }()
1019 go func() {
1020 foo := 0
1021 for {
1022 v := <-myc
1023 if v == 0 {
1024 break
1025 }
1026 for i := 0; i < localWork; i++ {
1027 foo *= 2
1028 foo /= 2
1029 }
1030 }
1031 c <- foo == 42
1032 }()
1033 }
1034 for p := 0; p < procs; p++ {
1035 <-c
1036 <-c
1037 }
1038 }
1039
1040 func BenchmarkChanProdCons0(b *testing.B) {
1041 benchmarkChanProdCons(b, 0, 0)
1042 }
1043
1044 func BenchmarkChanProdCons10(b *testing.B) {
1045 benchmarkChanProdCons(b, 10, 0)
1046 }
1047
1048 func BenchmarkChanProdCons100(b *testing.B) {
1049 benchmarkChanProdCons(b, 100, 0)
1050 }
1051
1052 func BenchmarkChanProdConsWork0(b *testing.B) {
1053 benchmarkChanProdCons(b, 0, 100)
1054 }
1055
1056 func BenchmarkChanProdConsWork10(b *testing.B) {
1057 benchmarkChanProdCons(b, 10, 100)
1058 }
1059
1060 func BenchmarkChanProdConsWork100(b *testing.B) {
1061 benchmarkChanProdCons(b, 100, 100)
1062 }
1063
1064 func BenchmarkSelectProdCons(b *testing.B) {
1065 const CallsPerSched = 1000
1066 procs := runtime.GOMAXPROCS(-1)
1067 N := int32(b.N / CallsPerSched)
1068 c := make(chan bool, 2*procs)
1069 myc := make(chan int, 128)
1070 myclose := make(chan bool)
1071 for p := 0; p < procs; p++ {
1072 go func() {
1073
1074 foo := 0
1075
1076 mytimer := time.After(time.Hour)
1077 for atomic.AddInt32(&N, -1) >= 0 {
1078 for g := 0; g < CallsPerSched; g++ {
1079
1080 for i := 0; i < 100; i++ {
1081 foo *= 2
1082 foo /= 2
1083 }
1084 select {
1085 case myc <- 1:
1086 case <-mytimer:
1087 case <-myclose:
1088 }
1089 }
1090 }
1091 myc <- 0
1092 c <- foo == 42
1093 }()
1094 go func() {
1095
1096 foo := 0
1097
1098 mytimer := time.After(time.Hour)
1099 loop:
1100 for {
1101 select {
1102 case v := <-myc:
1103 if v == 0 {
1104 break loop
1105 }
1106 case <-mytimer:
1107 case <-myclose:
1108 }
1109
1110 for i := 0; i < 100; i++ {
1111 foo *= 2
1112 foo /= 2
1113 }
1114 }
1115 c <- foo == 42
1116 }()
1117 }
1118 for p := 0; p < procs; p++ {
1119 <-c
1120 <-c
1121 }
1122 }
1123
1124 func BenchmarkChanCreation(b *testing.B) {
1125 b.RunParallel(func(pb *testing.PB) {
1126 for pb.Next() {
1127 myc := make(chan int, 1)
1128 myc <- 0
1129 <-myc
1130 }
1131 })
1132 }
1133
1134 func BenchmarkChanSem(b *testing.B) {
1135 type Empty struct{}
1136 myc := make(chan Empty, runtime.GOMAXPROCS(0))
1137 b.RunParallel(func(pb *testing.PB) {
1138 for pb.Next() {
1139 myc <- Empty{}
1140 <-myc
1141 }
1142 })
1143 }
1144
1145 func BenchmarkChanPopular(b *testing.B) {
1146 const n = 1000
1147 c := make(chan bool)
1148 var a []chan bool
1149 var wg sync.WaitGroup
1150 wg.Add(n)
1151 for j := 0; j < n; j++ {
1152 d := make(chan bool)
1153 a = append(a, d)
1154 go func() {
1155 for i := 0; i < b.N; i++ {
1156 select {
1157 case <-c:
1158 case <-d:
1159 }
1160 }
1161 wg.Done()
1162 }()
1163 }
1164 for i := 0; i < b.N; i++ {
1165 for _, d := range a {
1166 d <- true
1167 }
1168 }
1169 wg.Wait()
1170 }
1171
1172 func BenchmarkChanClosed(b *testing.B) {
1173 c := make(chan struct{})
1174 close(c)
1175 b.RunParallel(func(pb *testing.PB) {
1176 for pb.Next() {
1177 select {
1178 case <-c:
1179 default:
1180 b.Error("Unreachable")
1181 }
1182 }
1183 })
1184 }
1185
1186 var (
1187 alwaysFalse = false
1188 workSink = 0
1189 )
1190
1191 func localWork(w int) {
1192 foo := 0
1193 for i := 0; i < w; i++ {
1194 foo /= (foo + 1)
1195 }
1196 if alwaysFalse {
1197 workSink += foo
1198 }
1199 }
1200
View as plain text