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