mirror of
https://github.com/golang/go
synced 2024-10-04 04:41:23 -06:00
025abd530e
Uses atomic memory accesses to avoid the need to acquire and release schedlock on fast paths. benchmark old ns/op new ns/op delta runtime_test.BenchmarkSyscall 73 31 -56.63% runtime_test.BenchmarkSyscall-2 538 74 -86.23% runtime_test.BenchmarkSyscall-3 508 103 -79.72% runtime_test.BenchmarkSyscall-4 721 97 -86.52% runtime_test.BenchmarkSyscallWork 920 873 -5.11% runtime_test.BenchmarkSyscallWork-2 516 481 -6.78% runtime_test.BenchmarkSyscallWork-3 550 343 -37.64% runtime_test.BenchmarkSyscallWork-4 632 263 -58.39% (Intel Core i7 L640 2.13 GHz-based Lenovo X201s) Reduced a less artificial server benchmark from 11.5r 12.0u 8.0s to 8.3r 9.1u 1.0s. R=dvyukov, r, bradfitz, r, iant, iant CC=golang-dev https://golang.org/cl/4723042
126 lines
2.3 KiB
Go
126 lines
2.3 KiB
Go
// 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"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
var stop = make(chan bool, 1)
|
|
|
|
func perpetuumMobile() {
|
|
select {
|
|
case <-stop:
|
|
default:
|
|
go perpetuumMobile()
|
|
}
|
|
}
|
|
|
|
func TestStopTheWorldDeadlock(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Logf("skipping during short test")
|
|
return
|
|
}
|
|
maxprocs := runtime.GOMAXPROCS(3)
|
|
compl := make(chan bool, 2)
|
|
go func() {
|
|
for i := 0; i != 1000; i += 1 {
|
|
runtime.GC()
|
|
}
|
|
compl <- true
|
|
}()
|
|
go func() {
|
|
for i := 0; i != 1000; i += 1 {
|
|
runtime.GOMAXPROCS(3)
|
|
}
|
|
compl <- true
|
|
}()
|
|
go perpetuumMobile()
|
|
<-compl
|
|
<-compl
|
|
stop <- true
|
|
runtime.GOMAXPROCS(maxprocs)
|
|
}
|
|
|
|
func stackGrowthRecursive(i int) {
|
|
var pad [128]uint64
|
|
if i != 0 && pad[0] == 0 {
|
|
stackGrowthRecursive(i - 1)
|
|
}
|
|
}
|
|
|
|
func BenchmarkStackGrowth(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++ {
|
|
stackGrowthRecursive(10)
|
|
}
|
|
}
|
|
c <- true
|
|
}()
|
|
}
|
|
for p := 0; p < procs; p++ {
|
|
<-c
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|