adb0401dac
From-SVN: r178910
323 lines
5.7 KiB
Go
323 lines
5.7 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package runtime_test
|
|
|
|
import (
|
|
"runtime"
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestChanSendInterface(t *testing.T) {
|
|
type mt struct{}
|
|
m := &mt{}
|
|
c := make(chan interface{}, 1)
|
|
c <- m
|
|
select {
|
|
case c <- m:
|
|
default:
|
|
}
|
|
select {
|
|
case c <- m:
|
|
case c <- &mt{}:
|
|
default:
|
|
}
|
|
}
|
|
|
|
func TestPseudoRandomSend(t *testing.T) {
|
|
n := 100
|
|
c := make(chan int)
|
|
l := make([]int, n)
|
|
var m sync.Mutex
|
|
m.Lock()
|
|
go func() {
|
|
for i := 0; i < n; i++ {
|
|
runtime.Gosched()
|
|
l[i] = <-c
|
|
}
|
|
m.Unlock()
|
|
}()
|
|
for i := 0; i < n; i++ {
|
|
select {
|
|
case c <- 0:
|
|
case c <- 1:
|
|
}
|
|
}
|
|
m.Lock() // wait
|
|
n0 := 0
|
|
n1 := 0
|
|
for _, i := range l {
|
|
n0 += (i + 1) % 2
|
|
n1 += i
|
|
if n0 > n/10 && n1 > n/10 {
|
|
return
|
|
}
|
|
}
|
|
t.Errorf("Want pseudo random, got %d zeros and %d ones", n0, n1)
|
|
}
|
|
|
|
func BenchmarkSelectUncontended(b *testing.B) {
|
|
const CallsPerSched = 1000
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
N := int32(b.N / CallsPerSched)
|
|
c := make(chan bool, procs)
|
|
for p := 0; p < procs; p++ {
|
|
go func() {
|
|
myc1 := make(chan int, 1)
|
|
myc2 := make(chan int, 1)
|
|
myc1 <- 0
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
select {
|
|
case <-myc1:
|
|
myc2 <- 0
|
|
case <-myc2:
|
|
myc1 <- 0
|
|
}
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
func BenchmarkSelectContended(b *testing.B) {
|
|
const CallsPerSched = 1000
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
N := int32(b.N / CallsPerSched)
|
|
c := make(chan bool, procs)
|
|
myc1 := make(chan int, procs)
|
|
myc2 := make(chan int, procs)
|
|
for p := 0; p < procs; p++ {
|
|
myc1 <- 0
|
|
go func() {
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
select {
|
|
case <-myc1:
|
|
myc2 <- 0
|
|
case <-myc2:
|
|
myc1 <- 0
|
|
}
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
func BenchmarkSelectNonblock(b *testing.B) {
|
|
const CallsPerSched = 1000
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
N := int32(b.N / CallsPerSched)
|
|
c := make(chan bool, procs)
|
|
for p := 0; p < procs; p++ {
|
|
go func() {
|
|
myc1 := make(chan int)
|
|
myc2 := make(chan int)
|
|
myc3 := make(chan int, 1)
|
|
myc4 := make(chan int, 1)
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
select {
|
|
case <-myc1:
|
|
default:
|
|
}
|
|
select {
|
|
case myc2 <- 0:
|
|
default:
|
|
}
|
|
select {
|
|
case <-myc3:
|
|
default:
|
|
}
|
|
select {
|
|
case myc4 <- 0:
|
|
default:
|
|
}
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
func BenchmarkChanUncontended(b *testing.B) {
|
|
const CallsPerSched = 1000
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
N := int32(b.N / CallsPerSched)
|
|
c := make(chan bool, procs)
|
|
for p := 0; p < procs; p++ {
|
|
go func() {
|
|
myc := make(chan int, CallsPerSched)
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
myc <- 0
|
|
}
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
<-myc
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
func BenchmarkChanContended(b *testing.B) {
|
|
const CallsPerSched = 1000
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
N := int32(b.N / CallsPerSched)
|
|
c := make(chan bool, procs)
|
|
myc := make(chan int, procs*CallsPerSched)
|
|
for p := 0; p < procs; p++ {
|
|
go func() {
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
myc <- 0
|
|
}
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
<-myc
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
func BenchmarkChanSync(b *testing.B) {
|
|
const CallsPerSched = 1000
|
|
procs := 2
|
|
N := int32(b.N / CallsPerSched / procs * procs)
|
|
c := make(chan bool, procs)
|
|
myc := make(chan int)
|
|
for p := 0; p < procs; p++ {
|
|
go func() {
|
|
for {
|
|
i := atomic.AddInt32(&N, -1)
|
|
if i < 0 {
|
|
break
|
|
}
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
if i%2 == 0 {
|
|
<-myc
|
|
myc <- 0
|
|
} else {
|
|
myc <- 0
|
|
<-myc
|
|
}
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
func benchmarkChanProdCons(b *testing.B, chanSize, localWork int) {
|
|
const CallsPerSched = 1000
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
N := int32(b.N / CallsPerSched)
|
|
c := make(chan bool, 2*procs)
|
|
myc := make(chan int, chanSize)
|
|
for p := 0; p < procs; p++ {
|
|
go func() {
|
|
foo := 0
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
for i := 0; i < localWork; i++ {
|
|
foo *= 2
|
|
foo /= 2
|
|
}
|
|
myc <- 1
|
|
}
|
|
}
|
|
myc <- 0
|
|
c <- foo == 42
|
|
}()
|
|
go func() {
|
|
foo := 0
|
|
for {
|
|
v := <-myc
|
|
if v == 0 {
|
|
break
|
|
}
|
|
for i := 0; i < localWork; i++ {
|
|
foo *= 2
|
|
foo /= 2
|
|
}
|
|
}
|
|
c <- foo == 42
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
<-c
|
|
}
|
|
}
|
|
|
|
func BenchmarkChanProdCons0(b *testing.B) {
|
|
benchmarkChanProdCons(b, 0, 0)
|
|
}
|
|
|
|
func BenchmarkChanProdCons10(b *testing.B) {
|
|
benchmarkChanProdCons(b, 10, 0)
|
|
}
|
|
|
|
func BenchmarkChanProdCons100(b *testing.B) {
|
|
benchmarkChanProdCons(b, 100, 0)
|
|
}
|
|
|
|
func BenchmarkChanProdConsWork0(b *testing.B) {
|
|
benchmarkChanProdCons(b, 0, 100)
|
|
}
|
|
|
|
func BenchmarkChanProdConsWork10(b *testing.B) {
|
|
benchmarkChanProdCons(b, 10, 100)
|
|
}
|
|
|
|
func BenchmarkChanProdConsWork100(b *testing.B) {
|
|
benchmarkChanProdCons(b, 100, 100)
|
|
}
|
|
|
|
func BenchmarkChanCreation(b *testing.B) {
|
|
const CallsPerSched = 1000
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
N := int32(b.N / CallsPerSched)
|
|
c := make(chan bool, procs)
|
|
for p := 0; p < procs; p++ {
|
|
go func() {
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
myc := make(chan int, 1)
|
|
myc <- 0
|
|
<-myc
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|