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
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 r := float64(cnt1) / trials
487 e := math.Abs(r - 0.5)
488 t.Log(cnt1, cnt2, r, e)
489 if e > 4.891676/(2*math.Sqrt(trials)) {
490 t.Errorf("unfair select: in %d trials, results were %d, %d", trials, cnt1, cnt2)
491 }
492 close(done)
493 wg.Wait()
494 }
495
496 func TestChanSendInterface(t *testing.T) {
497 type mt struct{}
498 m := &mt{}
499 c := make(chan any, 1)
500 c <- m
501 select {
502 case c <- m:
503 default:
504 }
505 select {
506 case c <- m:
507 case c <- &mt{}:
508 default:
509 }
510 }
511
512 func TestPseudoRandomSend(t *testing.T) {
513 n := 100
514 for _, chanCap := range []int{0, n} {
515 c := make(chan int, chanCap)
516 l := make([]int, n)
517 var m sync.Mutex
518 m.Lock()
519 go func() {
520 for i := 0; i < n; i++ {
521 runtime.Gosched()
522 l[i] = <-c
523 }
524 m.Unlock()
525 }()
526 for i := 0; i < n; i++ {
527 select {
528 case c <- 1:
529 case c <- 0:
530 }
531 }
532 m.Lock()
533 n0 := 0
534 n1 := 0
535 for _, i := range l {
536 n0 += (i + 1) % 2
537 n1 += i
538 }
539 if n0 <= n/10 || n1 <= n/10 {
540 t.Errorf("Want pseudorandom, got %d zeros and %d ones (chan cap %d)", n0, n1, chanCap)
541 }
542 }
543 }
544
545 func TestMultiConsumer(t *testing.T) {
546 const nwork = 23
547 const niter = 271828
548
549 pn := []int{2, 3, 7, 11, 13, 17, 19, 23, 27, 31}
550
551 q := make(chan int, nwork*3)
552 r := make(chan int, nwork*3)
553
554
555 var wg sync.WaitGroup
556 for i := 0; i < nwork; i++ {
557 wg.Add(1)
558 go func(w int) {
559 for v := range q {
560
561 if pn[w%len(pn)] == v {
562 runtime.Gosched()
563 }
564 r <- v
565 }
566 wg.Done()
567 }(i)
568 }
569
570
571 expect := 0
572 go func() {
573 for i := 0; i < niter; i++ {
574 v := pn[i%len(pn)]
575 expect += v
576 q <- v
577 }
578 close(q)
579 wg.Wait()
580 close(r)
581 }()
582
583
584 n := 0
585 s := 0
586 for v := range r {
587 n++
588 s += v
589 }
590 if n != niter || s != expect {
591 t.Errorf("Expected sum %d (got %d) from %d iter (saw %d)",
592 expect, s, niter, n)
593 }
594 }
595
596 func TestShrinkStackDuringBlockedSend(t *testing.T) {
597
598
599
600
601 const n = 10
602 c := make(chan int)
603 done := make(chan struct{})
604
605 go func() {
606 for i := 0; i < n; i++ {
607 c <- i
608
609 stackGrowthRecursive(20)
610 }
611 done <- struct{}{}
612 }()
613
614 for i := 0; i < n; i++ {
615 x := <-c
616 if x != i {
617 t.Errorf("bad channel read: want %d, got %d", i, x)
618 }
619
620
621 time.Sleep(1 * time.Millisecond)
622
623 runtime.GC()
624 }
625 <-done
626 }
627
628 func TestNoShrinkStackWhileParking(t *testing.T) {
629 if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {
630 testenv.SkipFlaky(t, 49382)
631 }
632 if runtime.GOOS == "openbsd" {
633 testenv.SkipFlaky(t, 51482)
634 }
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653 const n = 10
654 send := func(c chan<- int, done chan struct{}) {
655 for i := 0; i < n; i++ {
656 c <- i
657
658
659
660
661
662
663 stackGrowthRecursive(20)
664 }
665 done <- struct{}{}
666 }
667 recv := func(c <-chan int, done chan struct{}) {
668 for i := 0; i < n; i++ {
669
670
671 time.Sleep(10 * time.Microsecond)
672 <-c
673 }
674 done <- struct{}{}
675 }
676 for i := 0; i < n*20; i++ {
677 c := make(chan int)
678 done := make(chan struct{})
679 go recv(c, done)
680 go send(c, done)
681
682
683
684 time.Sleep(50 * time.Microsecond)
685 runtime.GC()
686 <-done
687 <-done
688 }
689 }
690
691 func TestSelectDuplicateChannel(t *testing.T) {
692
693
694 c := make(chan int)
695 d := make(chan int)
696 e := make(chan int)
697
698
699 go func() {
700 select {
701 case <-c:
702 case <-c:
703 case <-d:
704 }
705 e <- 9
706 }()
707 time.Sleep(time.Millisecond)
708
709
710 go func() {
711 <-c
712 }()
713 time.Sleep(time.Millisecond)
714
715 d <- 7
716 <-e
717 c <- 8
718 }
719
720 func TestSelectStackAdjust(t *testing.T) {
721
722
723 c := make(chan *int)
724 d := make(chan *int)
725 ready1 := make(chan bool)
726 ready2 := make(chan bool)
727
728 f := func(ready chan bool, dup bool) {
729
730 stackGrowthRecursive((10 << 10) / (128 * 8))
731
732
733 ready <- true
734
735 val := 42
736 var cx *int
737 cx = &val
738
739 var c2 chan *int
740 var d2 chan *int
741 if dup {
742 c2 = c
743 d2 = d
744 }
745
746
747 select {
748 case cx = <-c:
749 case <-c2:
750 case <-d:
751 case <-d2:
752 }
753
754
755 if cx != &val {
756 t.Error("cx no longer points to val")
757 } else if val != 42 {
758 t.Error("val changed")
759 } else {
760 *cx = 43
761 if val != 43 {
762 t.Error("changing *cx failed to change val")
763 }
764 }
765 ready <- true
766 }
767
768 go f(ready1, false)
769 go f(ready2, true)
770
771
772 <-ready1
773 <-ready2
774 time.Sleep(10 * time.Millisecond)
775
776
777 runtime.GC()
778
779
780 close(d)
781 <-ready1
782 <-ready2
783 }
784
785 type struct0 struct{}
786
787 func BenchmarkMakeChan(b *testing.B) {
788 b.Run("Byte", func(b *testing.B) {
789 var x chan byte
790 for i := 0; i < b.N; i++ {
791 x = make(chan byte, 8)
792 }
793 close(x)
794 })
795 b.Run("Int", func(b *testing.B) {
796 var x chan int
797 for i := 0; i < b.N; i++ {
798 x = make(chan int, 8)
799 }
800 close(x)
801 })
802 b.Run("Ptr", func(b *testing.B) {
803 var x chan *byte
804 for i := 0; i < b.N; i++ {
805 x = make(chan *byte, 8)
806 }
807 close(x)
808 })
809 b.Run("Struct", func(b *testing.B) {
810 b.Run("0", func(b *testing.B) {
811 var x chan struct0
812 for i := 0; i < b.N; i++ {
813 x = make(chan struct0, 8)
814 }
815 close(x)
816 })
817 b.Run("32", func(b *testing.B) {
818 var x chan struct32
819 for i := 0; i < b.N; i++ {
820 x = make(chan struct32, 8)
821 }
822 close(x)
823 })
824 b.Run("40", func(b *testing.B) {
825 var x chan struct40
826 for i := 0; i < b.N; i++ {
827 x = make(chan struct40, 8)
828 }
829 close(x)
830 })
831 })
832 }
833
834 func BenchmarkChanNonblocking(b *testing.B) {
835 myc := make(chan int)
836 b.RunParallel(func(pb *testing.PB) {
837 for pb.Next() {
838 select {
839 case <-myc:
840 default:
841 }
842 }
843 })
844 }
845
846 func BenchmarkSelectUncontended(b *testing.B) {
847 b.RunParallel(func(pb *testing.PB) {
848 myc1 := make(chan int, 1)
849 myc2 := make(chan int, 1)
850 myc1 <- 0
851 for pb.Next() {
852 select {
853 case <-myc1:
854 myc2 <- 0
855 case <-myc2:
856 myc1 <- 0
857 }
858 }
859 })
860 }
861
862 func BenchmarkSelectSyncContended(b *testing.B) {
863 myc1 := make(chan int)
864 myc2 := make(chan int)
865 myc3 := make(chan int)
866 done := make(chan int)
867 b.RunParallel(func(pb *testing.PB) {
868 go func() {
869 for {
870 select {
871 case myc1 <- 0:
872 case myc2 <- 0:
873 case myc3 <- 0:
874 case <-done:
875 return
876 }
877 }
878 }()
879 for pb.Next() {
880 select {
881 case <-myc1:
882 case <-myc2:
883 case <-myc3:
884 }
885 }
886 })
887 close(done)
888 }
889
890 func BenchmarkSelectAsyncContended(b *testing.B) {
891 procs := runtime.GOMAXPROCS(0)
892 myc1 := make(chan int, procs)
893 myc2 := make(chan int, procs)
894 b.RunParallel(func(pb *testing.PB) {
895 myc1 <- 0
896 for pb.Next() {
897 select {
898 case <-myc1:
899 myc2 <- 0
900 case <-myc2:
901 myc1 <- 0
902 }
903 }
904 })
905 }
906
907 func BenchmarkSelectNonblock(b *testing.B) {
908 myc1 := make(chan int)
909 myc2 := make(chan int)
910 myc3 := make(chan int, 1)
911 myc4 := make(chan int, 1)
912 b.RunParallel(func(pb *testing.PB) {
913 for pb.Next() {
914 select {
915 case <-myc1:
916 default:
917 }
918 select {
919 case myc2 <- 0:
920 default:
921 }
922 select {
923 case <-myc3:
924 default:
925 }
926 select {
927 case myc4 <- 0:
928 default:
929 }
930 }
931 })
932 }
933
934 func BenchmarkChanUncontended(b *testing.B) {
935 const C = 100
936 b.RunParallel(func(pb *testing.PB) {
937 myc := make(chan int, C)
938 for pb.Next() {
939 for i := 0; i < C; i++ {
940 myc <- 0
941 }
942 for i := 0; i < C; i++ {
943 <-myc
944 }
945 }
946 })
947 }
948
949 func BenchmarkChanContended(b *testing.B) {
950 const C = 100
951 myc := make(chan int, C*runtime.GOMAXPROCS(0))
952 b.RunParallel(func(pb *testing.PB) {
953 for pb.Next() {
954 for i := 0; i < C; i++ {
955 myc <- 0
956 }
957 for i := 0; i < C; i++ {
958 <-myc
959 }
960 }
961 })
962 }
963
964 func benchmarkChanSync(b *testing.B, work int) {
965 const CallsPerSched = 1000
966 procs := 2
967 N := int32(b.N / CallsPerSched / procs * procs)
968 c := make(chan bool, procs)
969 myc := make(chan int)
970 for p := 0; p < procs; p++ {
971 go func() {
972 for {
973 i := atomic.AddInt32(&N, -1)
974 if i < 0 {
975 break
976 }
977 for g := 0; g < CallsPerSched; g++ {
978 if i%2 == 0 {
979 <-myc
980 localWork(work)
981 myc <- 0
982 localWork(work)
983 } else {
984 myc <- 0
985 localWork(work)
986 <-myc
987 localWork(work)
988 }
989 }
990 }
991 c <- true
992 }()
993 }
994 for p := 0; p < procs; p++ {
995 <-c
996 }
997 }
998
999 func BenchmarkChanSync(b *testing.B) {
1000 benchmarkChanSync(b, 0)
1001 }
1002
1003 func BenchmarkChanSyncWork(b *testing.B) {
1004 benchmarkChanSync(b, 1000)
1005 }
1006
1007 func benchmarkChanProdCons(b *testing.B, chanSize, localWork int) {
1008 const CallsPerSched = 1000
1009 procs := runtime.GOMAXPROCS(-1)
1010 N := int32(b.N / CallsPerSched)
1011 c := make(chan bool, 2*procs)
1012 myc := make(chan int, chanSize)
1013 for p := 0; p < procs; p++ {
1014 go func() {
1015 foo := 0
1016 for atomic.AddInt32(&N, -1) >= 0 {
1017 for g := 0; g < CallsPerSched; g++ {
1018 for i := 0; i < localWork; i++ {
1019 foo *= 2
1020 foo /= 2
1021 }
1022 myc <- 1
1023 }
1024 }
1025 myc <- 0
1026 c <- foo == 42
1027 }()
1028 go func() {
1029 foo := 0
1030 for {
1031 v := <-myc
1032 if v == 0 {
1033 break
1034 }
1035 for i := 0; i < localWork; i++ {
1036 foo *= 2
1037 foo /= 2
1038 }
1039 }
1040 c <- foo == 42
1041 }()
1042 }
1043 for p := 0; p < procs; p++ {
1044 <-c
1045 <-c
1046 }
1047 }
1048
1049 func BenchmarkChanProdCons0(b *testing.B) {
1050 benchmarkChanProdCons(b, 0, 0)
1051 }
1052
1053 func BenchmarkChanProdCons10(b *testing.B) {
1054 benchmarkChanProdCons(b, 10, 0)
1055 }
1056
1057 func BenchmarkChanProdCons100(b *testing.B) {
1058 benchmarkChanProdCons(b, 100, 0)
1059 }
1060
1061 func BenchmarkChanProdConsWork0(b *testing.B) {
1062 benchmarkChanProdCons(b, 0, 100)
1063 }
1064
1065 func BenchmarkChanProdConsWork10(b *testing.B) {
1066 benchmarkChanProdCons(b, 10, 100)
1067 }
1068
1069 func BenchmarkChanProdConsWork100(b *testing.B) {
1070 benchmarkChanProdCons(b, 100, 100)
1071 }
1072
1073 func BenchmarkSelectProdCons(b *testing.B) {
1074 const CallsPerSched = 1000
1075 procs := runtime.GOMAXPROCS(-1)
1076 N := int32(b.N / CallsPerSched)
1077 c := make(chan bool, 2*procs)
1078 myc := make(chan int, 128)
1079 myclose := make(chan bool)
1080 for p := 0; p < procs; p++ {
1081 go func() {
1082
1083 foo := 0
1084
1085 mytimer := time.After(time.Hour)
1086 for atomic.AddInt32(&N, -1) >= 0 {
1087 for g := 0; g < CallsPerSched; g++ {
1088
1089 for i := 0; i < 100; i++ {
1090 foo *= 2
1091 foo /= 2
1092 }
1093 select {
1094 case myc <- 1:
1095 case <-mytimer:
1096 case <-myclose:
1097 }
1098 }
1099 }
1100 myc <- 0
1101 c <- foo == 42
1102 }()
1103 go func() {
1104
1105 foo := 0
1106
1107 mytimer := time.After(time.Hour)
1108 loop:
1109 for {
1110 select {
1111 case v := <-myc:
1112 if v == 0 {
1113 break loop
1114 }
1115 case <-mytimer:
1116 case <-myclose:
1117 }
1118
1119 for i := 0; i < 100; i++ {
1120 foo *= 2
1121 foo /= 2
1122 }
1123 }
1124 c <- foo == 42
1125 }()
1126 }
1127 for p := 0; p < procs; p++ {
1128 <-c
1129 <-c
1130 }
1131 }
1132
1133 func BenchmarkReceiveDataFromClosedChan(b *testing.B) {
1134 count := b.N
1135 ch := make(chan struct{}, count)
1136 for i := 0; i < count; i++ {
1137 ch <- struct{}{}
1138 }
1139 close(ch)
1140
1141 b.ResetTimer()
1142 for range ch {
1143 }
1144 }
1145
1146 func BenchmarkChanCreation(b *testing.B) {
1147 b.RunParallel(func(pb *testing.PB) {
1148 for pb.Next() {
1149 myc := make(chan int, 1)
1150 myc <- 0
1151 <-myc
1152 }
1153 })
1154 }
1155
1156 func BenchmarkChanSem(b *testing.B) {
1157 type Empty struct{}
1158 myc := make(chan Empty, runtime.GOMAXPROCS(0))
1159 b.RunParallel(func(pb *testing.PB) {
1160 for pb.Next() {
1161 myc <- Empty{}
1162 <-myc
1163 }
1164 })
1165 }
1166
1167 func BenchmarkChanPopular(b *testing.B) {
1168 const n = 1000
1169 c := make(chan bool)
1170 var a []chan bool
1171 var wg sync.WaitGroup
1172 wg.Add(n)
1173 for j := 0; j < n; j++ {
1174 d := make(chan bool)
1175 a = append(a, d)
1176 go func() {
1177 for i := 0; i < b.N; i++ {
1178 select {
1179 case <-c:
1180 case <-d:
1181 }
1182 }
1183 wg.Done()
1184 }()
1185 }
1186 for i := 0; i < b.N; i++ {
1187 for _, d := range a {
1188 d <- true
1189 }
1190 }
1191 wg.Wait()
1192 }
1193
1194 func BenchmarkChanClosed(b *testing.B) {
1195 c := make(chan struct{})
1196 close(c)
1197 b.RunParallel(func(pb *testing.PB) {
1198 for pb.Next() {
1199 select {
1200 case <-c:
1201 default:
1202 b.Error("Unreachable")
1203 }
1204 }
1205 })
1206 }
1207
1208 var (
1209 alwaysFalse = false
1210 workSink = 0
1211 )
1212
1213 func localWork(w int) {
1214 foo := 0
1215 for i := 0; i < w; i++ {
1216 foo /= (foo + 1)
1217 }
1218 if alwaysFalse {
1219 workSink += foo
1220 }
1221 }
1222
View as plain text