2011-04-21 10:09:25 -06:00
|
|
|
// Copyright 2011 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"
|
2011-07-12 10:24:32 -06:00
|
|
|
"sync/atomic"
|
2011-04-21 10:09:25 -06:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2011-04-22 13:22:11 -06:00
|
|
|
var stop = make(chan bool, 1)
|
|
|
|
|
2011-04-21 10:09:25 -06:00
|
|
|
func perpetuumMobile() {
|
2011-04-22 13:22:11 -06:00
|
|
|
select {
|
|
|
|
case <-stop:
|
|
|
|
default:
|
|
|
|
go perpetuumMobile()
|
|
|
|
}
|
2011-04-21 10:09:25 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestStopTheWorldDeadlock(t *testing.T) {
|
2011-04-23 08:03:51 -06:00
|
|
|
if testing.Short() {
|
2013-01-23 23:32:10 -07:00
|
|
|
t.Skip("skipping during short test")
|
2011-04-23 08:03:51 -06:00
|
|
|
}
|
2011-05-31 08:38:51 -06:00
|
|
|
maxprocs := runtime.GOMAXPROCS(3)
|
|
|
|
compl := make(chan bool, 2)
|
2011-04-21 10:09:25 -06:00
|
|
|
go func() {
|
|
|
|
for i := 0; i != 1000; i += 1 {
|
|
|
|
runtime.GC()
|
|
|
|
}
|
2011-05-31 08:38:51 -06:00
|
|
|
compl <- true
|
2011-04-21 10:09:25 -06:00
|
|
|
}()
|
|
|
|
go func() {
|
|
|
|
for i := 0; i != 1000; i += 1 {
|
|
|
|
runtime.GOMAXPROCS(3)
|
|
|
|
}
|
2011-05-31 08:38:51 -06:00
|
|
|
compl <- true
|
2011-04-21 10:09:25 -06:00
|
|
|
}()
|
|
|
|
go perpetuumMobile()
|
|
|
|
<-compl
|
2011-05-31 08:38:51 -06:00
|
|
|
<-compl
|
2011-04-22 13:22:11 -06:00
|
|
|
stop <- true
|
2011-05-31 08:38:51 -06:00
|
|
|
runtime.GOMAXPROCS(maxprocs)
|
2011-04-21 10:09:25 -06:00
|
|
|
}
|
2011-07-12 10:24:32 -06:00
|
|
|
|
|
|
|
func stackGrowthRecursive(i int) {
|
|
|
|
var pad [128]uint64
|
|
|
|
if i != 0 && pad[0] == 0 {
|
|
|
|
stackGrowthRecursive(i - 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-09 22:57:06 -07:00
|
|
|
func benchmarkStackGrowth(b *testing.B, rec int) {
|
2011-07-12 10:24:32 -06:00
|
|
|
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 {
|
|
|
|
runtime.Gosched()
|
|
|
|
for g := 0; g < CallsPerSched; g++ {
|
2013-01-09 22:57:06 -07:00
|
|
|
stackGrowthRecursive(rec)
|
2011-07-12 10:24:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
c <- true
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
for p := 0; p < procs; p++ {
|
|
|
|
<-c
|
|
|
|
}
|
|
|
|
}
|
2011-07-19 09:01:17 -06:00
|
|
|
|
2013-01-09 22:57:06 -07:00
|
|
|
func BenchmarkStackGrowth(b *testing.B) {
|
|
|
|
benchmarkStackGrowth(b, 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkStackGrowthDeep(b *testing.B) {
|
|
|
|
benchmarkStackGrowth(b, 1024)
|
|
|
|
}
|
|
|
|
|
2011-07-19 09:01:17 -06:00
|
|
|
func BenchmarkSyscall(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 {
|
|
|
|
runtime.Gosched()
|
|
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
|
|
runtime.Entersyscall()
|
|
|
|
runtime.Exitsyscall()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c <- true
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
for p := 0; p < procs; p++ {
|
|
|
|
<-c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkSyscallWork(b *testing.B) {
|
|
|
|
const CallsPerSched = 1000
|
|
|
|
const LocalWork = 100
|
|
|
|
procs := runtime.GOMAXPROCS(-1)
|
|
|
|
N := int32(b.N / CallsPerSched)
|
|
|
|
c := make(chan bool, procs)
|
|
|
|
for p := 0; p < procs; p++ {
|
|
|
|
go func() {
|
|
|
|
foo := 42
|
|
|
|
for atomic.AddInt32(&N, -1) >= 0 {
|
|
|
|
runtime.Gosched()
|
|
|
|
for g := 0; g < CallsPerSched; g++ {
|
|
|
|
runtime.Entersyscall()
|
|
|
|
for i := 0; i < LocalWork; i++ {
|
|
|
|
foo *= 2
|
|
|
|
foo /= 2
|
|
|
|
}
|
|
|
|
runtime.Exitsyscall()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c <- foo == 42
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
for p := 0; p < procs; p++ {
|
|
|
|
<-c
|
|
|
|
}
|
|
|
|
}
|
2012-06-27 11:57:49 -06:00
|
|
|
|
|
|
|
func BenchmarkCreateGoroutines(b *testing.B) {
|
|
|
|
benchmarkCreateGoroutines(b, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkCreateGoroutinesParallel(b *testing.B) {
|
|
|
|
benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
|
|
|
|
}
|
|
|
|
|
|
|
|
func benchmarkCreateGoroutines(b *testing.B, procs int) {
|
|
|
|
c := make(chan bool)
|
|
|
|
var f func(n int)
|
|
|
|
f = func(n int) {
|
|
|
|
if n == 0 {
|
|
|
|
c <- true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
go f(n - 1)
|
|
|
|
}
|
|
|
|
for i := 0; i < procs; i++ {
|
|
|
|
go f(b.N / procs)
|
|
|
|
}
|
|
|
|
for i := 0; i < procs; i++ {
|
|
|
|
<-c
|
|
|
|
}
|
|
|
|
}
|