Home | History | Annotate | Download | only in runtime
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      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 			// Ensure that receive from empty chan blocks.
     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 			// 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 <- 0
     53 			c <- 0
     54 		}
     55 
     56 		{
     57 			// Ensure that send to full chan blocks.
     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 			// 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 			<-c
     78 		}
     79 
     80 		{
     81 			// Ensure that we receive 0 from closed chan.
     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 			// Ensure that close unblocks receive.
    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 			// 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 <- 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 			// Same, but using recv2.
    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 			// Send 1000 integers in 4 goroutines,
    149 			// ensure that we receive what we send.
    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 			// 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 <- 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 // This test checks that select acts on the state of the channels at one
    227 // moment in the execution, not over a smeared time window.
    228 // In the test, one goroutine does:
    229 //	create c1, c2
    230 //	make c1 ready for receiving
    231 //	create second goroutine
    232 //	make c2 ready for receiving
    233 //	make c1 no longer ready for receiving (if possible)
    234 // The second goroutine does a non-blocking select receiving from c1 and c2.
    235 // From the time the second goroutine is created, at least one of c1 and c2
    236 // is always ready for receiving, so the select in the second goroutine must
    237 // always receive from one or the other. It must never execute the default case.
    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 // Same as TestNonblockSelectRace, but close(c2) replaces c2 <- 1.
    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 	// Ensure that send/recv on the same chan in select
    303 	// does not crash nor deadlock.
    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 	// There are 4 goroutines that send N values on each of the chans,
    352 	// + 4 goroutines that receive N values on each of the chans,
    353 	// + 1 goroutine that sends N values on each of the chans in a single select,
    354 	// + 1 goroutine that receives N values on each of the chans in a single select.
    355 	// All these sends, receives and selects interact chaotically at runtime,
    356 	// but we are careful that this whole construct does not deadlock.
    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 	// If the select in the goroutine is fair,
    481 	// cnt1 and cnt2 should be about the same value.
    482 	// With 10,000 trials, the expected margin of error at
    483 	// a confidence level of five nines is 4.4172 / (2 * Sqrt(10000)).
    484 	r := float64(cnt1) / trials
    485 	e := math.Abs(r - 0.5)
    486 	t.Log(cnt1, cnt2, r, e)
    487 	if e > 4.4172/(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() // wait
    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 	// workers
    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 				// mess with the fifo-ish nature of range
    559 				if pn[w%len(pn)] == v {
    560 					runtime.Gosched()
    561 				}
    562 				r <- v
    563 			}
    564 			wg.Done()
    565 		}(i)
    566 	}
    567 
    568 	// feeder & closer
    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)  // no more work
    577 		wg.Wait() // workers done
    578 		close(r)  // ... so there can be no more results
    579 	}()
    580 
    581 	// consume & check
    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 	// make sure that channel operations still work when we are
    596 	// blocked on a channel send and we shrink the stack.
    597 	// NOTE: this test probably won't fail unless stack1.go:stackDebug
    598 	// is set to >= 1.
    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 			// use lots of stack, briefly.
    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 		// Waste some time so sender can finish using lots of stack
    618 		// and block in channel send.
    619 		time.Sleep(1 * time.Millisecond)
    620 		// trigger GC which will shrink the stack of the sender.
    621 		runtime.GC()
    622 	}
    623 	<-done
    624 }
    625 
    626 func TestSelectDuplicateChannel(t *testing.T) {
    627 	// This test makes sure we can queue a G on
    628 	// the same channel multiple times.
    629 	c := make(chan int)
    630 	d := make(chan int)
    631 	e := make(chan int)
    632 
    633 	// goroutine A
    634 	go func() {
    635 		select {
    636 		case <-c:
    637 		case <-c:
    638 		case <-d:
    639 		}
    640 		e <- 9
    641 	}()
    642 	time.Sleep(time.Millisecond) // make sure goroutine A gets queued first on c
    643 
    644 	// goroutine B
    645 	go func() {
    646 		<-c
    647 	}()
    648 	time.Sleep(time.Millisecond) // make sure goroutine B gets queued on c before continuing
    649 
    650 	d <- 7 // wake up A, it dequeues itself from c.  This operation used to corrupt c.recvq.
    651 	<-e    // A tells us it's done
    652 	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)
    653 }
    654 
    655 var selectSink interface{}
    656 
    657 func TestSelectStackAdjust(t *testing.T) {
    658 	// Test that channel receive slots that contain local stack
    659 	// pointers are adjusted correctly by stack shrinking.
    660 	c := make(chan *int)
    661 	d := make(chan *int)
    662 	ready1 := make(chan bool)
    663 	ready2 := make(chan bool)
    664 
    665 	f := func(ready chan bool, dup bool) {
    666 		// Temporarily grow the stack to 10K.
    667 		stackGrowthRecursive((10 << 10) / (128 * 8))
    668 
    669 		// We're ready to trigger GC and stack shrink.
    670 		ready <- true
    671 
    672 		val := 42
    673 		var cx *int
    674 		cx = &val
    675 
    676 		var c2 chan *int
    677 		var d2 chan *int
    678 		if dup {
    679 			c2 = c
    680 			d2 = d
    681 		}
    682 
    683 		// Receive from d. cx won't be affected.
    684 		select {
    685 		case cx = <-c:
    686 		case <-c2:
    687 		case <-d:
    688 		case <-d2:
    689 		}
    690 
    691 		// Check that pointer in cx was adjusted correctly.
    692 		if cx != &val {
    693 			t.Error("cx no longer points to val")
    694 		} else if val != 42 {
    695 			t.Error("val changed")
    696 		} else {
    697 			*cx = 43
    698 			if val != 43 {
    699 				t.Error("changing *cx failed to change val")
    700 			}
    701 		}
    702 		ready <- true
    703 	}
    704 
    705 	go f(ready1, false)
    706 	go f(ready2, true)
    707 
    708 	// Let the goroutines get into the select.
    709 	<-ready1
    710 	<-ready2
    711 	time.Sleep(10 * time.Millisecond)
    712 
    713 	// Force concurrent GC a few times.
    714 	var before, after runtime.MemStats
    715 	runtime.ReadMemStats(&before)
    716 	for i := 0; i < 100; i++ {
    717 		selectSink = new([1 << 20]byte)
    718 		runtime.ReadMemStats(&after)
    719 		if after.NumGC-before.NumGC >= 2 {
    720 			goto done
    721 		}
    722 	}
    723 	t.Fatal("failed to trigger concurrent GC")
    724 done:
    725 	selectSink = nil
    726 
    727 	// Wake selects.
    728 	close(d)
    729 	<-ready1
    730 	<-ready2
    731 }
    732 
    733 type struct0 struct{}
    734 
    735 func BenchmarkMakeChan(b *testing.B) {
    736 	b.Run("Byte", func(b *testing.B) {
    737 		var x chan byte
    738 		for i := 0; i < b.N; i++ {
    739 			x = make(chan byte, 8)
    740 		}
    741 		close(x)
    742 	})
    743 	b.Run("Int", func(b *testing.B) {
    744 		var x chan int
    745 		for i := 0; i < b.N; i++ {
    746 			x = make(chan int, 8)
    747 		}
    748 		close(x)
    749 	})
    750 	b.Run("Ptr", func(b *testing.B) {
    751 		var x chan *byte
    752 		for i := 0; i < b.N; i++ {
    753 			x = make(chan *byte, 8)
    754 		}
    755 		close(x)
    756 	})
    757 	b.Run("Struct", func(b *testing.B) {
    758 		b.Run("0", func(b *testing.B) {
    759 			var x chan struct0
    760 			for i := 0; i < b.N; i++ {
    761 				x = make(chan struct0, 8)
    762 			}
    763 			close(x)
    764 		})
    765 		b.Run("32", func(b *testing.B) {
    766 			var x chan struct32
    767 			for i := 0; i < b.N; i++ {
    768 				x = make(chan struct32, 8)
    769 			}
    770 			close(x)
    771 		})
    772 		b.Run("40", func(b *testing.B) {
    773 			var x chan struct40
    774 			for i := 0; i < b.N; i++ {
    775 				x = make(chan struct40, 8)
    776 			}
    777 			close(x)
    778 		})
    779 	})
    780 }
    781 
    782 func BenchmarkChanNonblocking(b *testing.B) {
    783 	myc := make(chan int)
    784 	b.RunParallel(func(pb *testing.PB) {
    785 		for pb.Next() {
    786 			select {
    787 			case <-myc:
    788 			default:
    789 			}
    790 		}
    791 	})
    792 }
    793 
    794 func BenchmarkSelectUncontended(b *testing.B) {
    795 	b.RunParallel(func(pb *testing.PB) {
    796 		myc1 := make(chan int, 1)
    797 		myc2 := make(chan int, 1)
    798 		myc1 <- 0
    799 		for pb.Next() {
    800 			select {
    801 			case <-myc1:
    802 				myc2 <- 0
    803 			case <-myc2:
    804 				myc1 <- 0
    805 			}
    806 		}
    807 	})
    808 }
    809 
    810 func BenchmarkSelectSyncContended(b *testing.B) {
    811 	myc1 := make(chan int)
    812 	myc2 := make(chan int)
    813 	myc3 := make(chan int)
    814 	done := make(chan int)
    815 	b.RunParallel(func(pb *testing.PB) {
    816 		go func() {
    817 			for {
    818 				select {
    819 				case myc1 <- 0:
    820 				case myc2 <- 0:
    821 				case myc3 <- 0:
    822 				case <-done:
    823 					return
    824 				}
    825 			}
    826 		}()
    827 		for pb.Next() {
    828 			select {
    829 			case <-myc1:
    830 			case <-myc2:
    831 			case <-myc3:
    832 			}
    833 		}
    834 	})
    835 	close(done)
    836 }
    837 
    838 func BenchmarkSelectAsyncContended(b *testing.B) {
    839 	procs := runtime.GOMAXPROCS(0)
    840 	myc1 := make(chan int, procs)
    841 	myc2 := make(chan int, procs)
    842 	b.RunParallel(func(pb *testing.PB) {
    843 		myc1 <- 0
    844 		for pb.Next() {
    845 			select {
    846 			case <-myc1:
    847 				myc2 <- 0
    848 			case <-myc2:
    849 				myc1 <- 0
    850 			}
    851 		}
    852 	})
    853 }
    854 
    855 func BenchmarkSelectNonblock(b *testing.B) {
    856 	myc1 := make(chan int)
    857 	myc2 := make(chan int)
    858 	myc3 := make(chan int, 1)
    859 	myc4 := make(chan int, 1)
    860 	b.RunParallel(func(pb *testing.PB) {
    861 		for pb.Next() {
    862 			select {
    863 			case <-myc1:
    864 			default:
    865 			}
    866 			select {
    867 			case myc2 <- 0:
    868 			default:
    869 			}
    870 			select {
    871 			case <-myc3:
    872 			default:
    873 			}
    874 			select {
    875 			case myc4 <- 0:
    876 			default:
    877 			}
    878 		}
    879 	})
    880 }
    881 
    882 func BenchmarkChanUncontended(b *testing.B) {
    883 	const C = 100
    884 	b.RunParallel(func(pb *testing.PB) {
    885 		myc := make(chan int, C)
    886 		for pb.Next() {
    887 			for i := 0; i < C; i++ {
    888 				myc <- 0
    889 			}
    890 			for i := 0; i < C; i++ {
    891 				<-myc
    892 			}
    893 		}
    894 	})
    895 }
    896 
    897 func BenchmarkChanContended(b *testing.B) {
    898 	const C = 100
    899 	myc := make(chan int, C*runtime.GOMAXPROCS(0))
    900 	b.RunParallel(func(pb *testing.PB) {
    901 		for pb.Next() {
    902 			for i := 0; i < C; i++ {
    903 				myc <- 0
    904 			}
    905 			for i := 0; i < C; i++ {
    906 				<-myc
    907 			}
    908 		}
    909 	})
    910 }
    911 
    912 func benchmarkChanSync(b *testing.B, work int) {
    913 	const CallsPerSched = 1000
    914 	procs := 2
    915 	N := int32(b.N / CallsPerSched / procs * procs)
    916 	c := make(chan bool, procs)
    917 	myc := make(chan int)
    918 	for p := 0; p < procs; p++ {
    919 		go func() {
    920 			for {
    921 				i := atomic.AddInt32(&N, -1)
    922 				if i < 0 {
    923 					break
    924 				}
    925 				for g := 0; g < CallsPerSched; g++ {
    926 					if i%2 == 0 {
    927 						<-myc
    928 						localWork(work)
    929 						myc <- 0
    930 						localWork(work)
    931 					} else {
    932 						myc <- 0
    933 						localWork(work)
    934 						<-myc
    935 						localWork(work)
    936 					}
    937 				}
    938 			}
    939 			c <- true
    940 		}()
    941 	}
    942 	for p := 0; p < procs; p++ {
    943 		<-c
    944 	}
    945 }
    946 
    947 func BenchmarkChanSync(b *testing.B) {
    948 	benchmarkChanSync(b, 0)
    949 }
    950 
    951 func BenchmarkChanSyncWork(b *testing.B) {
    952 	benchmarkChanSync(b, 1000)
    953 }
    954 
    955 func benchmarkChanProdCons(b *testing.B, chanSize, localWork int) {
    956 	const CallsPerSched = 1000
    957 	procs := runtime.GOMAXPROCS(-1)
    958 	N := int32(b.N / CallsPerSched)
    959 	c := make(chan bool, 2*procs)
    960 	myc := make(chan int, chanSize)
    961 	for p := 0; p < procs; p++ {
    962 		go func() {
    963 			foo := 0
    964 			for atomic.AddInt32(&N, -1) >= 0 {
    965 				for g := 0; g < CallsPerSched; g++ {
    966 					for i := 0; i < localWork; i++ {
    967 						foo *= 2
    968 						foo /= 2
    969 					}
    970 					myc <- 1
    971 				}
    972 			}
    973 			myc <- 0
    974 			c <- foo == 42
    975 		}()
    976 		go func() {
    977 			foo := 0
    978 			for {
    979 				v := <-myc
    980 				if v == 0 {
    981 					break
    982 				}
    983 				for i := 0; i < localWork; i++ {
    984 					foo *= 2
    985 					foo /= 2
    986 				}
    987 			}
    988 			c <- foo == 42
    989 		}()
    990 	}
    991 	for p := 0; p < procs; p++ {
    992 		<-c
    993 		<-c
    994 	}
    995 }
    996 
    997 func BenchmarkChanProdCons0(b *testing.B) {
    998 	benchmarkChanProdCons(b, 0, 0)
    999 }
   1000 
   1001 func BenchmarkChanProdCons10(b *testing.B) {
   1002 	benchmarkChanProdCons(b, 10, 0)
   1003 }
   1004 
   1005 func BenchmarkChanProdCons100(b *testing.B) {
   1006 	benchmarkChanProdCons(b, 100, 0)
   1007 }
   1008 
   1009 func BenchmarkChanProdConsWork0(b *testing.B) {
   1010 	benchmarkChanProdCons(b, 0, 100)
   1011 }
   1012 
   1013 func BenchmarkChanProdConsWork10(b *testing.B) {
   1014 	benchmarkChanProdCons(b, 10, 100)
   1015 }
   1016 
   1017 func BenchmarkChanProdConsWork100(b *testing.B) {
   1018 	benchmarkChanProdCons(b, 100, 100)
   1019 }
   1020 
   1021 func BenchmarkSelectProdCons(b *testing.B) {
   1022 	const CallsPerSched = 1000
   1023 	procs := runtime.GOMAXPROCS(-1)
   1024 	N := int32(b.N / CallsPerSched)
   1025 	c := make(chan bool, 2*procs)
   1026 	myc := make(chan int, 128)
   1027 	myclose := make(chan bool)
   1028 	for p := 0; p < procs; p++ {
   1029 		go func() {
   1030 			// Producer: sends to myc.
   1031 			foo := 0
   1032 			// Intended to not fire during benchmarking.
   1033 			mytimer := time.After(time.Hour)
   1034 			for atomic.AddInt32(&N, -1) >= 0 {
   1035 				for g := 0; g < CallsPerSched; g++ {
   1036 					// Model some local work.
   1037 					for i := 0; i < 100; i++ {
   1038 						foo *= 2
   1039 						foo /= 2
   1040 					}
   1041 					select {
   1042 					case myc <- 1:
   1043 					case <-mytimer:
   1044 					case <-myclose:
   1045 					}
   1046 				}
   1047 			}
   1048 			myc <- 0
   1049 			c <- foo == 42
   1050 		}()
   1051 		go func() {
   1052 			// Consumer: receives from myc.
   1053 			foo := 0
   1054 			// Intended to not fire during benchmarking.
   1055 			mytimer := time.After(time.Hour)
   1056 		loop:
   1057 			for {
   1058 				select {
   1059 				case v := <-myc:
   1060 					if v == 0 {
   1061 						break loop
   1062 					}
   1063 				case <-mytimer:
   1064 				case <-myclose:
   1065 				}
   1066 				// Model some local work.
   1067 				for i := 0; i < 100; i++ {
   1068 					foo *= 2
   1069 					foo /= 2
   1070 				}
   1071 			}
   1072 			c <- foo == 42
   1073 		}()
   1074 	}
   1075 	for p := 0; p < procs; p++ {
   1076 		<-c
   1077 		<-c
   1078 	}
   1079 }
   1080 
   1081 func BenchmarkChanCreation(b *testing.B) {
   1082 	b.RunParallel(func(pb *testing.PB) {
   1083 		for pb.Next() {
   1084 			myc := make(chan int, 1)
   1085 			myc <- 0
   1086 			<-myc
   1087 		}
   1088 	})
   1089 }
   1090 
   1091 func BenchmarkChanSem(b *testing.B) {
   1092 	type Empty struct{}
   1093 	myc := make(chan Empty, runtime.GOMAXPROCS(0))
   1094 	b.RunParallel(func(pb *testing.PB) {
   1095 		for pb.Next() {
   1096 			myc <- Empty{}
   1097 			<-myc
   1098 		}
   1099 	})
   1100 }
   1101 
   1102 func BenchmarkChanPopular(b *testing.B) {
   1103 	const n = 1000
   1104 	c := make(chan bool)
   1105 	var a []chan bool
   1106 	var wg sync.WaitGroup
   1107 	wg.Add(n)
   1108 	for j := 0; j < n; j++ {
   1109 		d := make(chan bool)
   1110 		a = append(a, d)
   1111 		go func() {
   1112 			for i := 0; i < b.N; i++ {
   1113 				select {
   1114 				case <-c:
   1115 				case <-d:
   1116 				}
   1117 			}
   1118 			wg.Done()
   1119 		}()
   1120 	}
   1121 	for i := 0; i < b.N; i++ {
   1122 		for _, d := range a {
   1123 			d <- true
   1124 		}
   1125 	}
   1126 	wg.Wait()
   1127 }
   1128 
   1129 var (
   1130 	alwaysFalse = false
   1131 	workSink    = 0
   1132 )
   1133 
   1134 func localWork(w int) {
   1135 	foo := 0
   1136 	for i := 0; i < w; i++ {
   1137 		foo /= (foo + 1)
   1138 	}
   1139 	if alwaysFalse {
   1140 		workSink += foo
   1141 	}
   1142 }
   1143