mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: fix CPU underutilization
runtime.newproc/ready are deliberately sloppy about waking new M's, they only ensure that there is at least 1 spinning M. Currently to compensate for that, schedule() checks if the current P has local work and there are no spinning M's, it wakes up another one. It does not work if goroutines do not call schedule. With this change a spinning M wakes up another M when it finds work to do. It's also not ideal, but it fixes the underutilization. A proper check would require to know the exact number of runnable G's, but it's too expensive to maintain. Fixes #5586. R=rsc CC=gobot, golang-dev https://golang.org/cl/9776044
This commit is contained in:
parent
eac6bee7c1
commit
15a1c3d1e4
2 changed files with 51 additions and 14 deletions
|
|
@ -93,6 +93,30 @@ func TestYieldLocked(t *testing.T) {
|
|||
<-c
|
||||
}
|
||||
|
||||
func TestGoroutineParallelism(t *testing.T) {
|
||||
const P = 4
|
||||
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
|
||||
for try := 0; try < 10; try++ {
|
||||
done := make(chan bool)
|
||||
x := uint32(0)
|
||||
for p := 0; p < P; p++ {
|
||||
// Test that all P goroutines are scheduled at the same time
|
||||
go func(p int) {
|
||||
for i := 0; i < 3; i++ {
|
||||
expected := uint32(P*i + p)
|
||||
for atomic.LoadUint32(&x) != expected {
|
||||
}
|
||||
atomic.StoreUint32(&x, expected+1)
|
||||
}
|
||||
done <- true
|
||||
}(p)
|
||||
}
|
||||
for p := 0; p < P; p++ {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockLocked(t *testing.T) {
|
||||
const N = 10
|
||||
c := make(chan bool)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue