Defer inside loop; deferred calls accumulate until the function returns, not until the loop iteration ends. This can cause resource leaks
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
1// Copyright 2009 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package runtime_test67import (8 "internal/testenv"9 "math"10 "runtime"11 "sync"12 "sync/atomic"13 "testing"14 "time"15)1617func TestChan(t *testing.T) {18 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))19 N := 20020 if testing.Short() {21 N = 2022 }23 for chanCap := 0; chanCap < N; chanCap++ {24 {25 // Ensure that receive from empty chan blocks.26 c := make(chan int, chanCap)27 recv1 := false28 go func() {29 _ = <-c30 recv1 = true31 }()32 recv2 := false33 go func() {34 _, _ = <-c35 recv2 = true36 }()37 time.Sleep(time.Millisecond)38 if recv1 || recv2 {39 t.Fatalf("chan[%d]: receive from empty chan", chanCap)40 }41 // Ensure that non-blocking receive does not block.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 <- 053 c <- 054 }5556 {57 // Ensure that send to full chan blocks.58 c := make(chan int, chanCap)59 for i := 0; i < chanCap; i++ {60 c <- i61 }62 sent := uint32(0)63 go func() {64 c <- 065 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 // Ensure that non-blocking send does not block.72 select {73 case c <- 0:74 t.Fatalf("chan[%d]: send to full chan", chanCap)75 default:76 }77 <-c78 }7980 {81 // Ensure that we receive 0 from closed chan.82 c := make(chan int, chanCap)83 for i := 0; i < chanCap; i++ {84 c <- i85 }86 close(c)87 for i := 0; i < chanCap; i++ {88 v := <-c89 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 }100101 {102 // Ensure that close unblocks receive.103 c := make(chan int, chanCap)104 done := make(chan bool)105 go func() {106 v, ok := <-c107 done <- v == 0 && ok == false108 }()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 }115116 {117 // Send 100 integers,118 // ensure that we receive them non-corrupted in FIFO order.119 c := make(chan int, chanCap)120 go func() {121 for i := 0; i < 100; i++ {122 c <- i123 }124 }()125 for i := 0; i < 100; i++ {126 v := <-c127 if v != i {128 t.Fatalf("chan[%d]: received %v, expected %v", chanCap, v, i)129 }130 }131132 // Same, but using recv2.133 go func() {134 for i := 0; i < 100; i++ {135 c <- i136 }137 }()138 for i := 0; i < 100; i++ {139 v, ok := <-c140 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 }147148 // Send 1000 integers in 4 goroutines,149 // ensure that we receive what we send.150 const P = 4151 const L = 1000152 for p := 0; p < P; p++ {153 go func() {154 for i := 0; i < L; i++ {155 c <- i156 }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 := <-c165 recv[v] = recv[v] + 1166 }167 done <- recv168 }()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] + v174 }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 }185186 {187 // Test len/cap.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 <- i194 }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 }199200 }201}202203func TestNonblockRecvRace(t *testing.T) {204 n := 10000205 if testing.Short() {206 n = 100207 }208 for i := 0; i < n; i++ {209 c := make(chan int, 1)210 c <- 1211 go func() {212 select {213 case <-c:214 default:215 t.Error("chan is not ready")216 }217 }()218 close(c)219 <-c220 if t.Failed() {221 return222 }223 }224}225226// This test checks that select acts on the state of the channels at one227// moment in the execution, not over a smeared time window.228// In the test, one goroutine does:229//230// create c1, c2231// make c1 ready for receiving232// create second goroutine233// make c2 ready for receiving234// make c1 no longer ready for receiving (if possible)235//236// The second goroutine does a non-blocking select receiving from c1 and c2.237// From the time the second goroutine is created, at least one of c1 and c2238// is always ready for receiving, so the select in the second goroutine must239// always receive from one or the other. It must never execute the default case.240func TestNonblockSelectRace(t *testing.T) {241 n := 100000242 if testing.Short() {243 n = 1000244 }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 <- 1250 go func() {251 select {252 case <-c1:253 case <-c2:254 default:255 done <- false256 return257 }258 done <- true259 }()260 c2 <- 1261 select {262 case <-c1:263 default:264 }265 if !<-done {266 t.Fatal("no chan is ready")267 }268 }269}270271// Same as TestNonblockSelectRace, but close(c2) replaces c2 <- 1.272func TestNonblockSelectRace2(t *testing.T) {273 n := 100000274 if testing.Short() {275 n = 1000276 }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 <- 1282 go func() {283 select {284 case <-c1:285 case <-c2:286 default:287 done <- false288 return289 }290 done <- true291 }()292 close(c2)293 select {294 case <-c1:295 default:296 }297 if !<-done {298 t.Fatal("no chan is ready")299 }300 }301}302303func TestSelfSelect(t *testing.T) {304 // Ensure that send/recv on the same chan in select305 // does not crash nor deadlock.306 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))307 for _, chanCap := range []int{0, 10} {308 var wg sync.WaitGroup309 wg.Add(2)310 c := make(chan int, chanCap)311 for p := 0; p < 2; p++ {312 go func() {313 defer wg.Done()314 for i := 0; i < 1000; i++ {315 if p == 0 || i%2 == 0 {316 select {317 case c <- p:318 case v := <-c:319 if chanCap == 0 && v == p {320 t.Errorf("self receive")321 return322 }323 }324 } else {325 select {326 case v := <-c:327 if chanCap == 0 && v == p {328 t.Errorf("self receive")329 return330 }331 case c <- p:332 }333 }334 }335 }()336 }337 wg.Wait()338 }339}340341func TestSelectStress(t *testing.T) {342 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(10))343 var c [4]chan int344 c[0] = make(chan int)345 c[1] = make(chan int)346 c[2] = make(chan int, 2)347 c[3] = make(chan int, 3)348 N := int(1e5)349 if testing.Short() {350 N /= 10351 }352 // There are 4 goroutines that send N values on each of the chans,353 // + 4 goroutines that receive N values on each of the chans,354 // + 1 goroutine that sends N values on each of the chans in a single select,355 // + 1 goroutine that receives N values on each of the chans in a single select.356 // All these sends, receives and selects interact chaotically at runtime,357 // but we are careful that this whole construct does not deadlock.358 var wg sync.WaitGroup359 wg.Add(10)360 for k := 0; k < 4; k++ {361 go func() {362 for i := 0; i < N; i++ {363 c[k] <- 0364 }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]int376 c1 := c377 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] = nil383 }384 case c1[2] <- 0:385 n[2]++386 if n[2] == N {387 c1[2] = nil388 }389 case c1[0] <- 0:390 n[0]++391 if n[0] == N {392 c1[0] = nil393 }394 case c1[1] <- 0:395 n[1]++396 if n[1] == N {397 c1[1] = nil398 }399 }400 }401 wg.Done()402 }()403 go func() {404 var n [4]int405 c1 := c406 for i := 0; i < 4*N; i++ {407 select {408 case <-c1[0]:409 n[0]++410 if n[0] == N {411 c1[0] = nil412 }413 case <-c1[1]:414 n[1]++415 if n[1] == N {416 c1[1] = nil417 }418 case <-c1[2]:419 n[2]++420 if n[2] == N {421 c1[2] = nil422 }423 case <-c1[3]:424 n[3]++425 if n[3] == N {426 c1[3] = nil427 }428 }429 }430 wg.Done()431 }()432 wg.Wait()433}434435func TestSelectFairness(t *testing.T) {436 const trials = 10000437 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 <- 1444 c2 <- 2445 }446 c3 := make(chan byte)447 c4 := make(chan byte)448 out := make(chan byte)449 done := make(chan byte)450 var wg sync.WaitGroup451 wg.Add(1)452 go func() {453 defer wg.Done()454 for {455 var b byte456 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 return466 }467 }468 }()469 cnt1, cnt2 := 0, 0470 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 // If the select in the goroutine is fair,481 // cnt1 and cnt2 should be about the same value.482 // See if we're more than 10 sigma away from the expected value.483 // 10 sigma is a lot, but we're ok with some systematic bias as484 // long as it isn't too severe.485 const mean = trials * 0.5486 const variance = trials * 0.5 * (1 - 0.5)487 stddev := math.Sqrt(variance)488 if math.Abs(float64(cnt1-mean)) > 10*stddev {489 t.Errorf("unfair select: in %d trials, results were %d, %d", trials, cnt1, cnt2)490 }491 close(done)492 wg.Wait()493}494495func TestChanSendInterface(t *testing.T) {496 type mt struct{}497 m := &mt{}498 c := make(chan any, 1)499 c <- m500 select {501 case c <- m:502 default:503 }504 select {505 case c <- m:506 case c <- &mt{}:507 default:508 }509}510511func TestPseudoRandomSend(t *testing.T) {512 n := 100513 for _, chanCap := range []int{0, n} {514 c := make(chan int, chanCap)515 l := make([]int, n)516 var m sync.Mutex517 m.Lock()518 go func() {519 for i := 0; i < n; i++ {520 runtime.Gosched()521 l[i] = <-c522 }523 m.Unlock()524 }()525 for i := 0; i < n; i++ {526 select {527 case c <- 1:528 case c <- 0:529 }530 }531 m.Lock() // wait532 n0 := 0533 n1 := 0534 for _, i := range l {535 n0 += (i + 1) % 2536 n1 += i537 }538 if n0 <= n/10 || n1 <= n/10 {539 t.Errorf("Want pseudorandom, got %d zeros and %d ones (chan cap %d)", n0, n1, chanCap)540 }541 }542}543544func TestMultiConsumer(t *testing.T) {545 const nwork = 23546 const niter = 271828547548 pn := []int{2, 3, 7, 11, 13, 17, 19, 23, 27, 31}549550 q := make(chan int, nwork*3)551 r := make(chan int, nwork*3)552553 // workers554 var wg sync.WaitGroup555 for i := 0; i < nwork; i++ {556 wg.Add(1)557 go func(w int) {558 for v := range q {559 // mess with the fifo-ish nature of range560 if pn[w%len(pn)] == v {561 runtime.Gosched()562 }563 r <- v564 }565 wg.Done()566 }(i)567 }568569 // feeder & closer570 expect := 0571 go func() {572 for i := 0; i < niter; i++ {573 v := pn[i%len(pn)]574 expect += v575 q <- v576 }577 close(q) // no more work578 wg.Wait() // workers done579 close(r) // ... so there can be no more results580 }()581582 // consume & check583 n := 0584 s := 0585 for v := range r {586 n++587 s += v588 }589 if n != niter || s != expect {590 t.Errorf("Expected sum %d (got %d) from %d iter (saw %d)",591 expect, s, niter, n)592 }593}594595func TestShrinkStackDuringBlockedSend(t *testing.T) {596 // make sure that channel operations still work when we are597 // blocked on a channel send and we shrink the stack.598 // NOTE: this test probably won't fail unless stack1.go:stackDebug599 // is set to >= 1.600 const n = 10601 c := make(chan int)602 done := make(chan struct{})603604 go func() {605 for i := 0; i < n; i++ {606 c <- i607 // use lots of stack, briefly.608 stackGrowthRecursive(20)609 }610 done <- struct{}{}611 }()612613 for i := 0; i < n; i++ {614 x := <-c615 if x != i {616 t.Errorf("bad channel read: want %d, got %d", i, x)617 }618 // Waste some time so sender can finish using lots of stack619 // and block in channel send.620 time.Sleep(1 * time.Millisecond)621 // trigger GC which will shrink the stack of the sender.622 runtime.GC()623 }624 <-done625}626627func TestNoShrinkStackWhileParking(t *testing.T) {628 if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {629 testenv.SkipFlaky(t, 49382)630 }631 if runtime.GOOS == "openbsd" {632 testenv.SkipFlaky(t, 51482)633 }634635 // The goal of this test is to trigger a "racy sudog adjustment"636 // throw. Basically, there's a window between when a goroutine637 // becomes available for preemption for stack scanning (and thus,638 // stack shrinking) but before the goroutine has fully parked on a639 // channel. See issue 40641 for more details on the problem.640 //641 // The way we try to induce this failure is to set up two642 // goroutines: a sender and a receiver that communicate across643 // a channel. We try to set up a situation where the sender644 // grows its stack temporarily then *fully* blocks on a channel645 // often. Meanwhile a GC is triggered so that we try to get a646 // mark worker to shrink the sender's stack and race with the647 // sender parking.648 //649 // Unfortunately the race window here is so small that we650 // either need a ridiculous number of iterations, or we add651 // "usleep(1000)" to park_m, just before the unlockf call.652 const n = 10653 send := func(c chan<- int, done chan struct{}) {654 for i := 0; i < n; i++ {655 c <- i656 // Use lots of stack briefly so that657 // the GC is going to want to shrink us658 // when it scans us. Make sure not to659 // do any function calls otherwise660 // in order to avoid us shrinking ourselves661 // when we're preempted.662 stackGrowthRecursive(20)663 }664 done <- struct{}{}665 }666 recv := func(c <-chan int, done chan struct{}) {667 for i := 0; i < n; i++ {668 // Sleep here so that the sender always669 // fully blocks.670 time.Sleep(10 * time.Microsecond)671 <-c672 }673 done <- struct{}{}674 }675 for i := 0; i < n*20; i++ {676 c := make(chan int)677 done := make(chan struct{})678 go recv(c, done)679 go send(c, done)680 // Wait a little bit before triggering681 // the GC to make sure the sender and682 // receiver have gotten into their groove.683 time.Sleep(50 * time.Microsecond)684 runtime.GC()685 <-done686 <-done687 }688}689690func TestSelectDuplicateChannel(t *testing.T) {691 // This test makes sure we can queue a G on692 // the same channel multiple times.693 c := make(chan int)694 d := make(chan int)695 e := make(chan int)696697 // goroutine A698 go func() {699 select {700 case <-c:701 case <-c:702 case <-d:703 }704 e <- 9705 }()706 time.Sleep(time.Millisecond) // make sure goroutine A gets queued first on c707708 // goroutine B709 go func() {710 <-c711 }()712 time.Sleep(time.Millisecond) // make sure goroutine B gets queued on c before continuing713714 d <- 7 // wake up A, it dequeues itself from c. This operation used to corrupt c.recvq.715 <-e // A tells us it's done716 c <- 8 // wake up B. This operation used to fail because c.recvq was corrupted (it tries to wake up an already running G instead of B)717}718719func TestSelectStackAdjust(t *testing.T) {720 // Test that channel receive slots that contain local stack721 // pointers are adjusted correctly by stack shrinking.722 c := make(chan *int)723 d := make(chan *int)724 ready1 := make(chan bool)725 ready2 := make(chan bool)726727 f := func(ready chan bool, dup bool) {728 // Temporarily grow the stack to 10K.729 stackGrowthRecursive((10 << 10) / (128 * 8))730731 // We're ready to trigger GC and stack shrink.732 ready <- true733734 val := 42735 var cx *int736 cx = &val737738 var c2 chan *int739 var d2 chan *int740 if dup {741 c2 = c742 d2 = d743 }744745 // Receive from d. cx won't be affected.746 select {747 case cx = <-c:748 case <-c2:749 case <-d:750 case <-d2:751 }752753 // Check that pointer in cx was adjusted correctly.754 if cx != &val {755 t.Error("cx no longer points to val")756 } else if val != 42 {757 t.Error("val changed")758 } else {759 *cx = 43760 if val != 43 {761 t.Error("changing *cx failed to change val")762 }763 }764 ready <- true765 }766767 go f(ready1, false)768 go f(ready2, true)769770 // Let the goroutines get into the select.771 <-ready1772 <-ready2773 time.Sleep(10 * time.Millisecond)774775 // Force concurrent GC to shrink the stacks.776 runtime.GC()777778 // Wake selects.779 close(d)780 <-ready1781 <-ready2782}783784type struct0 struct{}785786func BenchmarkMakeChan(b *testing.B) {787 b.Run("Byte", func(b *testing.B) {788 var x chan byte789 for i := 0; i < b.N; i++ {790 x = make(chan byte, 8)791 }792 close(x)793 })794 b.Run("Int", func(b *testing.B) {795 var x chan int796 for i := 0; i < b.N; i++ {797 x = make(chan int, 8)798 }799 close(x)800 })801 b.Run("Ptr", func(b *testing.B) {802 var x chan *byte803 for i := 0; i < b.N; i++ {804 x = make(chan *byte, 8)805 }806 close(x)807 })808 b.Run("Struct", func(b *testing.B) {809 b.Run("0", func(b *testing.B) {810 var x chan struct0811 for i := 0; i < b.N; i++ {812 x = make(chan struct0, 8)813 }814 close(x)815 })816 b.Run("32", func(b *testing.B) {817 var x chan struct32818 for i := 0; i < b.N; i++ {819 x = make(chan struct32, 8)820 }821 close(x)822 })823 b.Run("40", func(b *testing.B) {824 var x chan struct40825 for i := 0; i < b.N; i++ {826 x = make(chan struct40, 8)827 }828 close(x)829 })830 })831}832833func BenchmarkChanNonblocking(b *testing.B) {834 myc := make(chan int)835 b.RunParallel(func(pb *testing.PB) {836 for pb.Next() {837 select {838 case <-myc:839 default:840 }841 }842 })843}844845func BenchmarkSelectUncontended(b *testing.B) {846 b.RunParallel(func(pb *testing.PB) {847 myc1 := make(chan int, 1)848 myc2 := make(chan int, 1)849 myc1 <- 0850 for pb.Next() {851 select {852 case <-myc1:853 myc2 <- 0854 case <-myc2:855 myc1 <- 0856 }857 }858 })859}860861func BenchmarkSelectSyncContended(b *testing.B) {862 myc1 := make(chan int)863 myc2 := make(chan int)864 myc3 := make(chan int)865 done := make(chan int)866 b.RunParallel(func(pb *testing.PB) {867 go func() {868 for {869 select {870 case myc1 <- 0:871 case myc2 <- 0:872 case myc3 <- 0:873 case <-done:874 return875 }876 }877 }()878 for pb.Next() {879 select {880 case <-myc1:881 case <-myc2:882 case <-myc3:883 }884 }885 })886 close(done)887}888889func BenchmarkSelectAsyncContended(b *testing.B) {890 procs := runtime.GOMAXPROCS(0)891 myc1 := make(chan int, procs)892 myc2 := make(chan int, procs)893 b.RunParallel(func(pb *testing.PB) {894 myc1 <- 0895 for pb.Next() {896 select {897 case <-myc1:898 myc2 <- 0899 case <-myc2:900 myc1 <- 0901 }902 }903 })904}905906func BenchmarkSelectNonblock(b *testing.B) {907 myc1 := make(chan int)908 myc2 := make(chan int)909 myc3 := make(chan int, 1)910 myc4 := make(chan int, 1)911 b.RunParallel(func(pb *testing.PB) {912 for pb.Next() {913 select {914 case <-myc1:915 default:916 }917 select {918 case myc2 <- 0:919 default:920 }921 select {922 case <-myc3:923 default:924 }925 select {926 case myc4 <- 0:927 default:928 }929 }930 })931}932933func BenchmarkChanUncontended(b *testing.B) {934 const C = 100935 b.RunParallel(func(pb *testing.PB) {936 myc := make(chan int, C)937 for pb.Next() {938 for i := 0; i < C; i++ {939 myc <- 0940 }941 for i := 0; i < C; i++ {942 <-myc943 }944 }945 })946}947948func BenchmarkChanContended(b *testing.B) {949 const C = 100950 myc := make(chan int, C*runtime.GOMAXPROCS(0))951 b.RunParallel(func(pb *testing.PB) {952 for pb.Next() {953 for i := 0; i < C; i++ {954 myc <- 0955 }956 for i := 0; i < C; i++ {957 <-myc958 }959 }960 })961}962963func benchmarkChanSync(b *testing.B, work int) {964 const CallsPerSched = 1000965 procs := 2966 N := int32(b.N / CallsPerSched / procs * procs)967 c := make(chan bool, procs)968 myc := make(chan int)969 for p := 0; p < procs; p++ {970 go func() {971 for {972 i := atomic.AddInt32(&N, -1)973 if i < 0 {974 break975 }976 for g := 0; g < CallsPerSched; g++ {977 if i%2 == 0 {978 <-myc979 localWork(work)980 myc <- 0981 localWork(work)982 } else {983 myc <- 0984 localWork(work)985 <-myc986 localWork(work)987 }988 }989 }990 c <- true991 }()992 }993 for p := 0; p < procs; p++ {994 <-c995 }996}997998func BenchmarkChanSync(b *testing.B) {999 benchmarkChanSync(b, 0)1000}10011002func BenchmarkChanSyncWork(b *testing.B) {1003 benchmarkChanSync(b, 1000)1004}10051006func benchmarkChanProdCons(b *testing.B, chanSize, localWork int) {1007 const CallsPerSched = 10001008 procs := runtime.GOMAXPROCS(-1)1009 N := int32(b.N / CallsPerSched)1010 c := make(chan bool, 2*procs)1011 myc := make(chan int, chanSize)1012 for p := 0; p < procs; p++ {1013 go func() {1014 foo := 01015 for atomic.AddInt32(&N, -1) >= 0 {1016 for g := 0; g < CallsPerSched; g++ {1017 for i := 0; i < localWork; i++ {1018 foo *= 21019 foo /= 21020 }1021 myc <- 11022 }1023 }1024 myc <- 01025 c <- foo == 421026 }()1027 go func() {1028 foo := 01029 for {1030 v := <-myc1031 if v == 0 {1032 break1033 }1034 for i := 0; i < localWork; i++ {1035 foo *= 21036 foo /= 21037 }1038 }1039 c <- foo == 421040 }()1041 }1042 for p := 0; p < procs; p++ {1043 <-c1044 <-c1045 }1046}10471048func BenchmarkChanProdCons0(b *testing.B) {1049 benchmarkChanProdCons(b, 0, 0)1050}10511052func BenchmarkChanProdCons10(b *testing.B) {1053 benchmarkChanProdCons(b, 10, 0)1054}10551056func BenchmarkChanProdCons100(b *testing.B) {1057 benchmarkChanProdCons(b, 100, 0)1058}10591060func BenchmarkChanProdConsWork0(b *testing.B) {1061 benchmarkChanProdCons(b, 0, 100)1062}10631064func BenchmarkChanProdConsWork10(b *testing.B) {1065 benchmarkChanProdCons(b, 10, 100)1066}10671068func BenchmarkChanProdConsWork100(b *testing.B) {1069 benchmarkChanProdCons(b, 100, 100)1070}10711072func BenchmarkSelectProdCons(b *testing.B) {1073 const CallsPerSched = 10001074 procs := runtime.GOMAXPROCS(-1)1075 N := int32(b.N / CallsPerSched)1076 c := make(chan bool, 2*procs)1077 myc := make(chan int, 128)1078 myclose := make(chan bool)1079 for p := 0; p < procs; p++ {1080 go func() {1081 // Producer: sends to myc.1082 foo := 01083 // Intended to not fire during benchmarking.1084 mytimer := time.After(time.Hour)1085 for atomic.AddInt32(&N, -1) >= 0 {1086 for g := 0; g < CallsPerSched; g++ {1087 // Model some local work.1088 for i := 0; i < 100; i++ {1089 foo *= 21090 foo /= 21091 }1092 select {1093 case myc <- 1:1094 case <-mytimer:1095 case <-myclose:1096 }1097 }1098 }1099 myc <- 01100 c <- foo == 421101 }()1102 go func() {1103 // Consumer: receives from myc.1104 foo := 01105 // Intended to not fire during benchmarking.1106 mytimer := time.After(time.Hour)1107 loop:1108 for {1109 select {1110 case v := <-myc:1111 if v == 0 {1112 break loop1113 }1114 case <-mytimer:1115 case <-myclose:1116 }1117 // Model some local work.1118 for i := 0; i < 100; i++ {1119 foo *= 21120 foo /= 21121 }1122 }1123 c <- foo == 421124 }()1125 }1126 for p := 0; p < procs; p++ {1127 <-c1128 <-c1129 }1130}11311132func BenchmarkReceiveDataFromClosedChan(b *testing.B) {1133 count := b.N1134 ch := make(chan struct{}, count)1135 for i := 0; i < count; i++ {1136 ch <- struct{}{}1137 }1138 close(ch)11391140 b.ResetTimer()1141 for range ch {1142 }1143}11441145func BenchmarkChanCreation(b *testing.B) {1146 b.RunParallel(func(pb *testing.PB) {1147 for pb.Next() {1148 myc := make(chan int, 1)1149 myc <- 01150 <-myc1151 }1152 })1153}11541155func BenchmarkChanSem(b *testing.B) {1156 type Empty struct{}1157 myc := make(chan Empty, runtime.GOMAXPROCS(0))1158 b.RunParallel(func(pb *testing.PB) {1159 for pb.Next() {1160 myc <- Empty{}1161 <-myc1162 }1163 })1164}11651166func BenchmarkChanPopular(b *testing.B) {1167 const n = 10001168 c := make(chan bool)1169 var a []chan bool1170 var wg sync.WaitGroup1171 wg.Add(n)1172 for j := 0; j < n; j++ {1173 d := make(chan bool)1174 a = append(a, d)1175 go func() {1176 for i := 0; i < b.N; i++ {1177 select {1178 case <-c:1179 case <-d:1180 }1181 }1182 wg.Done()1183 }()1184 }1185 for i := 0; i < b.N; i++ {1186 for _, d := range a {1187 d <- true1188 }1189 }1190 wg.Wait()1191}11921193func BenchmarkChanClosed(b *testing.B) {1194 c := make(chan struct{})1195 close(c)1196 b.RunParallel(func(pb *testing.PB) {1197 for pb.Next() {1198 select {1199 case <-c:1200 default:1201 b.Error("Unreachable")1202 }1203 }1204 })1205}12061207var (1208 alwaysFalse = false1209 workSink = 01210)12111212func localWork(w int) {1213 foo := 01214 for i := 0; i < w; i++ {1215 foo /= (foo + 1)1216 }1217 if alwaysFalse {1218 workSink += foo1219 }1220}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.