aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgcwork.go
diff options
context:
space:
mode:
authorRick Hudson <rlh@golang.org>2015-06-01 18:16:03 -0400
committerRick Hudson <rlh@golang.org>2015-06-18 21:38:46 +0000
commit90a19961f2b885ee253b2d51820977dc9c635f0c (patch)
tree43af66519513a18c72e22cc773dd4d662f2bb3fa /src/runtime/mgcwork.go
parente6d2112ba9fb4823aa14bec5e32c57533d135787 (diff)
downloadgo-90a19961f2b885ee253b2d51820977dc9c635f0c.tar.gz
go-90a19961f2b885ee253b2d51820977dc9c635f0c.zip
runtime: reduce latency by aggressively ending mark phase
Some latency regressions have crept into our system over the past few weeks. This CL fixes those by having the mark phase more aggressively blacken objects so that the mark termination phase, a STW phase, has less work to do. Three approaches were taken when the mark phase believes it has no more work to do, ie all the work buffers are empty. If things have gone well the mark phase is correct and there is in fact little or no work. In that case the following items will take very little time. If the mark phase is wrong this CL will ferret that work out and give the mark phase a chance to deal with it concurrently before mark termination begins. When the mark phase first appears to be out of work, it does three things: 1) It switches from allocating white to allocating black to reduce the number of unmarked objects reachable only from stacks. 2) It flushes and disables per-P GC work caches so all work must be in globally visible work buffers. 3) It rescans the global roots---the BSS and data segments---so there are fewer objects to blacken during mark termination. We do not rescan stacks at this point, though that could be done in a later CL. After these steps, it again drains the global work buffers. On a lightly loaded machine the garbage benchmark has reduced the number of GC cycles with latency > 10 ms from 83 out of 4083 cycles down to 2 out of 3995 cycles. Maximum latency was reduced from 60+ msecs down to 20 ms. Change-Id: I152285b48a7e56c5083a02e8e4485dd39c990492 Reviewed-on: https://go-review.googlesource.com/10590 Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/mgcwork.go')
-rw-r--r--src/runtime/mgcwork.go20
1 files changed, 16 insertions, 4 deletions
diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go
index 226c65635f..4a1455c860 100644
--- a/src/runtime/mgcwork.go
+++ b/src/runtime/mgcwork.go
@@ -240,7 +240,7 @@ func (b *workbuf) logput(entry int) {
return
}
if !b.inuse {
- println("runtime:logput fails log entry=", entry,
+ println("runtime: logput fails log entry=", entry,
"b.log[0]=", b.log[0], "b.log[1]=", b.log[1],
"b.log[2]=", b.log[2], "b.log[3]=", b.log[3])
throw("logput: put not legal")
@@ -388,10 +388,18 @@ func getfull(entry int) *workbuf {
return b
}
- xadd(&work.nwait, +1)
+ incnwait := xadd(&work.nwait, +1)
+ if incnwait > work.nproc {
+ println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
+ throw("work.nwait > work.nproc")
+ }
for i := 0; ; i++ {
if work.full != 0 || work.partial != 0 {
- xadd(&work.nwait, -1)
+ decnwait := xadd(&work.nwait, -1)
+ if decnwait == work.nproc {
+ println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
+ throw("work.nwait > work.nproc")
+ }
b = (*workbuf)(lfstackpop(&work.full))
if b == nil {
b = (*workbuf)(lfstackpop(&work.partial))
@@ -401,7 +409,11 @@ func getfull(entry int) *workbuf {
b.checknonempty()
return b
}
- xadd(&work.nwait, +1)
+ incnwait := xadd(&work.nwait, +1)
+ if incnwait > work.nproc {
+ println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
+ throw("work.nwait > work.nproc")
+ }
}
if work.nwait == work.nproc {
return nil