diff options
| author | Austin Clements <austin@google.com> | 2016-10-30 20:20:17 -0400 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2016-11-20 22:44:17 +0000 |
| commit | 49ea9207b6512c2400de11bc097d974bb527ba63 (patch) | |
| tree | 24b580415d0a35ba75e2b422a25885b1cfe891c6 /src/runtime/proc.go | |
| parent | 7dc97d9e328edc800e2ce41d5b211ef4e0ef41d0 (diff) | |
| download | go-49ea9207b6512c2400de11bc097d974bb527ba63.tar.xz | |
runtime: exit idle worker if there's higher-priority work
Idle GC workers trigger whenever there's a GC running and the
scheduler doesn't find any other work. However, they currently run for
a full scheduler quantum (~10ms) once started.
This is really bad for event-driven applications, where work may come
in on the network hundreds of times during that window. In the
go-gcbench rpc benchmark, this is bad enough to often cause effective
STWs where all Ps are in the idle worker. When this happens, we don't
even poll the network any more (except for the background 10ms poll in
sysmon), so we don't even know there's more work to do.
Fix this by making idle workers check with the scheduler roughly every
100 µs to see if there's any higher-priority work the P should be
doing. This check includes polling the network for incoming work.
Fixes #16528.
Change-Id: I6f62ebf6d36a92368da9891bafbbfd609b9bd003
Reviewed-on: https://go-review.googlesource.com/32433
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
Diffstat (limited to 'src/runtime/proc.go')
| -rw-r--r-- | src/runtime/proc.go | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 90e6d18ee2..1b21b37de8 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -2053,6 +2053,27 @@ stop: goto top } +// pollWork returns true if there is non-background work this P could +// be doing. This is a fairly lightweight check to be used for +// background work loops, like idle GC. It checks a subset of the +// conditions checked by the actual scheduler. +func pollWork() bool { + if sched.runqsize != 0 { + return true + } + p := getg().m.p.ptr() + if !runqempty(p) { + return true + } + if netpollinited() && sched.lastpoll != 0 { + if gp := netpoll(false); gp != nil { + injectglist(gp) + return true + } + } + return false +} + func resetspinning() { _g_ := getg() if !_g_.m.spinning { |
