Source file
src/runtime/chan_test.go
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 any, 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 if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {
628 testenv.SkipFlaky(t, 49382)
629 }
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648 const n = 10
649 send := func(c chan<- int, done chan struct{}) {
650 for i := 0; i < n; i++ {
651 c <- i
652
653
654
655
656
657
658 stackGrowthRecursive(20)
659 }
660 done <- struct{}{}
661 }
662 recv := func(c <-chan int, done chan struct{}) {
663 for i := 0; i < n; i++ {
664
665
666 time.Sleep(10 * time.Microsecond)
667 <-c
668 }
669 done <- struct{}{}
670 }
671 for i := 0; i < n*20; i++ {
672 c := make(chan int)
673 done := make(chan struct{})
674 go recv(c, done)
675 go send(c, done)
676
677
678
679 time.Sleep(50 * time.Microsecond)
680 runtime.GC()
681 <-done
682 <-done
683 }
684 }
685
686 func TestSelectDuplicateChannel(t *testing.T) {
687
688
689 c := make(chan int)
690 d := make(chan int)
691 e := make(chan int)
692
693
694 go func() {
695 select {
696 case <-c:
697 case <-c:
698 case <-d:
699 }
700 e <- 9
701 }()
702 time.Sleep(time.Millisecond)
703
704
705 go func() {
706 <-c
707 }()
708 time.Sleep(time.Millisecond)
709
710 d <- 7
711 <-e
712 c <- 8
713 }
714
715 func TestSelectStackAdjust(t *testing.T) {
716
717
718 c := make(chan *int)
719 d := make(chan *int)
720 ready1 := make(chan bool)
721 ready2 := make(chan bool)
722
723 f := func(ready chan bool, dup bool) {
724
725 stackGrowthRecursive((10 << 10) / (128 * 8))
726
727
728 ready <- true
729
730 val := 42
731 var cx *int
732 cx = &val
733
734 var c2 chan *int
735 var d2 chan *int
736 if dup {
737 c2 = c
738 d2 = d
739 }
740
741
742 select {
743 case cx = <-c:
744 case <-c2:
745 case <-d:
746 case <-d2:
747 }
748
749
750 if cx != &val {
751 t.Error("cx no longer points to val")
752 } else if val != 42 {
753 t.Error("val changed")
754 } else {
755 *cx = 43
756 if val != 43 {
757 t.Error("changing *cx failed to change val")
758 }
759 }
760 ready <- true
761 }
762
763 go f(ready1, false)
764 go f(ready2, true)
765
766
767 <-ready1
768 <-ready2
769 time.Sleep(10 * time.Millisecond)
770
771
772 runtime.GC()
773
774
775 close(d)
776 <-ready1
777 <-ready2
778 }
779
780 type struct0 struct{}
781
782 func BenchmarkMakeChan(b *testing.B) {
783 b.Run("Byte", func(b *testing.B) {
784 var x chan byte
785 for i := 0; i < b.N; i++ {
786 x = make(chan byte, 8)
787 }
788 close(x)
789 })
790 b.Run("Int", func(b *testing.B) {
791 var x chan int
792 for i := 0; i < b.N; i++ {
793 x = make(chan int, 8)
794 }
795 close(x)
796 })
797 b.Run("Ptr", func(b *testing.B) {
798 var x chan *byte
799 for i := 0; i < b.N; i++ {
800 x = make(chan *byte, 8)
801 }
802 close(x)
803 })
804 b.Run("Struct", func(b *testing.B) {
805 b.Run("0", func(b *testing.B) {
806 var x chan struct0
807 for i := 0; i < b.N; i++ {
808 x = make(chan struct0, 8)
809 }
810 close(x)
811 })
812 b.Run("32", func(b *testing.B) {
813 var x chan struct32
814 for i := 0; i < b.N; i++ {
815 x = make(chan struct32, 8)
816 }
817 close(x)
818 })
819 b.Run("40", func(b *testing.B) {
820 var x chan struct40
821 for i := 0; i < b.N; i++ {
822 x = make(chan struct40, 8)
823 }
824 close(x)
825 })
826 })
827 }
828
829 func BenchmarkChanNonblocking(b *testing.B) {
830 myc := make(chan int)
831 b.RunParallel(func(pb *testing.PB) {
832 for pb.Next() {
833 select {
834 case <-myc:
835 default:
836 }
837 }
838 })
839 }
840
841 func BenchmarkSelectUncontended(b *testing.B) {
842 b.RunParallel(func(pb *testing.PB) {
843 myc1 := make(chan int, 1)
844 myc2 := make(chan int, 1)
845 myc1 <- 0
846 for pb.Next() {
847 select {
848 case <-myc1:
849 myc2 <- 0
850 case <-myc2:
851 myc1 <- 0
852 }
853 }
854 })
855 }
856
857 func BenchmarkSelectSyncContended(b *testing.B) {
858 myc1 := make(chan int)
859 myc2 := make(chan int)
860 myc3 := make(chan int)
861 done := make(chan int)
862 b.RunParallel(func(pb *testing.PB) {
863 go func() {
864 for {
865 select {
866 case myc1 <- 0:
867 case myc2 <- 0:
868 case myc3 <- 0:
869 case <-done:
870 return
871 }
872 }
873 }()
874 for pb.Next() {
875 select {
876 case <-myc1:
877 case <-myc2:
878 case <-myc3:
879 }
880 }
881 })
882 close(done)
883 }
884
885 func BenchmarkSelectAsyncContended(b *testing.B) {
886 procs := runtime.GOMAXPROCS(0)
887 myc1 := make(chan int, procs)
888 myc2 := make(chan int, procs)
889 b.RunParallel(func(pb *testing.PB) {
890 myc1 <- 0
891 for pb.Next() {
892 select {
893 case <-myc1:
894 myc2 <- 0
895 case <-myc2:
896 myc1 <- 0
897 }
898 }
899 })
900 }
901
902 func BenchmarkSelectNonblock(b *testing.B) {
903 myc1 := make(chan int)
904 myc2 := make(chan int)
905 myc3 := make(chan int, 1)
906 myc4 := make(chan int, 1)
907 b.RunParallel(func(pb *testing.PB) {
908 for pb.Next() {
909 select {
910 case <-myc1:
911 default:
912 }
913 select {
914 case myc2 <- 0:
915 default:
916 }
917 select {
918 case <-myc3:
919 default:
920 }
921 select {
922 case myc4 <- 0:
923 default:
924 }
925 }
926 })
927 }
928
929 func BenchmarkChanUncontended(b *testing.B) {
930 const C = 100
931 b.RunParallel(func(pb *testing.PB) {
932 myc := make(chan int, C)
933 for pb.Next() {
934 for i := 0; i < C; i++ {
935 myc <- 0
936 }
937 for i := 0; i < C; i++ {
938 <-myc
939 }
940 }
941 })
942 }
943
944 func BenchmarkChanContended(b *testing.B) {
945 const C = 100
946 myc := make(chan int, C*runtime.GOMAXPROCS(0))
947 b.RunParallel(func(pb *testing.PB) {
948 for pb.Next() {
949 for i := 0; i < C; i++ {
950 myc <- 0
951 }
952 for i := 0; i < C; i++ {
953 <-myc
954 }
955 }
956 })
957 }
958
959 func benchmarkChanSync(b *testing.B, work int) {
960 const CallsPerSched = 1000
961 procs := 2
962 N := int32(b.N / CallsPerSched / procs * procs)
963 c := make(chan bool, procs)
964 myc := make(chan int)
965 for p := 0; p < procs; p++ {
966 go func() {
967 for {
968 i := atomic.AddInt32(&N, -1)
969 if i < 0 {
970 break
971 }
972 for g := 0; g < CallsPerSched; g++ {
973 if i%2 == 0 {
974 <-myc
975 localWork(work)
976 myc <- 0
977 localWork(work)
978 } else {
979 myc <- 0
980 localWork(work)
981 <-myc
982 localWork(work)
983 }
984 }
985 }
986 c <- true
987 }()
988 }
989 for p := 0; p < procs; p++ {
990 <-c
991 }
992 }
993
994 func BenchmarkChanSync(b *testing.B) {
995 benchmarkChanSync(b, 0)
996 }
997
998 func BenchmarkChanSyncWork(b *testing.B) {
999 benchmarkChanSync(b, 1000)
1000 }
1001
1002 func benchmarkChanProdCons(b *testing.B, chanSize, localWork int) {
1003 const CallsPerSched = 1000
1004 procs := runtime.GOMAXPROCS(-1)
1005 N := int32(b.N / CallsPerSched)
1006 c := make(chan bool, 2*procs)
1007 myc := make(chan int, chanSize)
1008 for p := 0; p < procs; p++ {
1009 go func() {
1010 foo := 0
1011 for atomic.AddInt32(&N, -1) >= 0 {
1012 for g := 0; g < CallsPerSched; g++ {
1013 for i := 0; i < localWork; i++ {
1014 foo *= 2
1015 foo /= 2
1016 }
1017 myc <- 1
1018 }
1019 }
1020 myc <- 0
1021 c <- foo == 42
1022 }()
1023 go func() {
1024 foo := 0
1025 for {
1026 v := <-myc
1027 if v == 0 {
1028 break
1029 }
1030 for i := 0; i < localWork; i++ {
1031 foo *= 2
1032 foo /= 2
1033 }
1034 }
1035 c <- foo == 42
1036 }()
1037 }
1038 for p := 0; p < procs; p++ {
1039 <-c
1040 <-c
1041 }
1042 }
1043
1044 func BenchmarkChanProdCons0(b *testing.B) {
1045 benchmarkChanProdCons(b, 0, 0)
1046 }
1047
1048 func BenchmarkChanProdCons10(b *testing.B) {
1049 benchmarkChanProdCons(b, 10, 0)
1050 }
1051
1052 func BenchmarkChanProdCons100(b *testing.B) {
1053 benchmarkChanProdCons(b, 100, 0)
1054 }
1055
1056 func BenchmarkChanProdConsWork0(b *testing.B) {
1057 benchmarkChanProdCons(b, 0, 100)
1058 }
1059
1060 func BenchmarkChanProdConsWork10(b *testing.B) {
1061 benchmarkChanProdCons(b, 10, 100)
1062 }
1063
1064 func BenchmarkChanProdConsWork100(b *testing.B) {
1065 benchmarkChanProdCons(b, 100, 100)
1066 }
1067
1068 func BenchmarkSelectProdCons(b *testing.B) {
1069 const CallsPerSched = 1000
1070 procs := runtime.GOMAXPROCS(-1)
1071 N := int32(b.N / CallsPerSched)
1072 c := make(chan bool, 2*procs)
1073 myc := make(chan int, 128)
1074 myclose := make(chan bool)
1075 for p := 0; p < procs; p++ {
1076 go func() {
1077
1078 foo := 0
1079
1080 mytimer := time.After(time.Hour)
1081 for atomic.AddInt32(&N, -1) >= 0 {
1082 for g := 0; g < CallsPerSched; g++ {
1083
1084 for i := 0; i < 100; i++ {
1085 foo *= 2
1086 foo /= 2
1087 }
1088 select {
1089 case myc <- 1:
1090 case <-mytimer:
1091 case <-myclose:
1092 }
1093 }
1094 }
1095 myc <- 0
1096 c <- foo == 42
1097 }()
1098 go func() {
1099
1100 foo := 0
1101
1102 mytimer := time.After(time.Hour)
1103 loop:
1104 for {
1105 select {
1106 case v := <-myc:
1107 if v == 0 {
1108 break loop
1109 }
1110 case <-mytimer:
1111 case <-myclose:
1112 }
1113
1114 for i := 0; i < 100; i++ {
1115 foo *= 2
1116 foo /= 2
1117 }
1118 }
1119 c <- foo == 42
1120 }()
1121 }
1122 for p := 0; p < procs; p++ {
1123 <-c
1124 <-c
1125 }
1126 }
1127
1128 func BenchmarkChanCreation(b *testing.B) {
1129 b.RunParallel(func(pb *testing.PB) {
1130 for pb.Next() {
1131 myc := make(chan int, 1)
1132 myc <- 0
1133 <-myc
1134 }
1135 })
1136 }
1137
1138 func BenchmarkChanSem(b *testing.B) {
1139 type Empty struct{}
1140 myc := make(chan Empty, runtime.GOMAXPROCS(0))
1141 b.RunParallel(func(pb *testing.PB) {
1142 for pb.Next() {
1143 myc <- Empty{}
1144 <-myc
1145 }
1146 })
1147 }
1148
1149 func BenchmarkChanPopular(b *testing.B) {
1150 const n = 1000
1151 c := make(chan bool)
1152 var a []chan bool
1153 var wg sync.WaitGroup
1154 wg.Add(n)
1155 for j := 0; j < n; j++ {
1156 d := make(chan bool)
1157 a = append(a, d)
1158 go func() {
1159 for i := 0; i < b.N; i++ {
1160 select {
1161 case <-c:
1162 case <-d:
1163 }
1164 }
1165 wg.Done()
1166 }()
1167 }
1168 for i := 0; i < b.N; i++ {
1169 for _, d := range a {
1170 d <- true
1171 }
1172 }
1173 wg.Wait()
1174 }
1175
1176 func BenchmarkChanClosed(b *testing.B) {
1177 c := make(chan struct{})
1178 close(c)
1179 b.RunParallel(func(pb *testing.PB) {
1180 for pb.Next() {
1181 select {
1182 case <-c:
1183 default:
1184 b.Error("Unreachable")
1185 }
1186 }
1187 })
1188 }
1189
1190 var (
1191 alwaysFalse = false
1192 workSink = 0
1193 )
1194
1195 func localWork(w int) {
1196 foo := 0
1197 for i := 0; i < w; i++ {
1198 foo /= (foo + 1)
1199 }
1200 if alwaysFalse {
1201 workSink += foo
1202 }
1203 }
1204
View as plain text