From d5b40b6ac261c987244ba0131c272b0b7ebc25cf Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 5 Jun 2015 11:51:49 -0400 Subject: [PATCH] runtime: add GODEBUG gcshrinkstackoff, gcstackbarrieroff, and gcstoptheworld variables While we're here, update the documentation and delete variables with no effect. Change-Id: I4df0d266dff880df61b488ed547c2870205862f0 Reviewed-on: https://go-review.googlesource.com/10790 Reviewed-by: Austin Clements --- src/runtime/extern.go | 45 +++++++++++++++++++++++++++-------------- src/runtime/mgc.go | 6 ++++++ src/runtime/mgcmark.go | 4 ++++ src/runtime/runtime1.go | 36 ++++++++++++++++++--------------- src/runtime/stack1.go | 4 ++++ 5 files changed, 64 insertions(+), 31 deletions(-) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index 476c3c5ae3..3882229370 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -21,8 +21,8 @@ is GOGC=100. Setting GOGC=off disables the garbage collector entirely. The runtime/debug package's SetGCPercent function allows changing this percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent. -The GODEBUG variable controls debug output from the runtime. GODEBUG value is -a comma-separated list of name=val pairs. Supported names are: +The GODEBUG variable controls debugging variables within the runtime. +It is a comma-separated list of name=val pairs setting these named variables: allocfreetrace: setting allocfreetrace=1 causes every allocation to be profiled and a stack trace printed on each object's allocation and free. @@ -31,13 +31,34 @@ a comma-separated list of name=val pairs. Supported names are: where each object is allocated on a unique page and addresses are never recycled. + gccheckmark: setting gccheckmark=1 enables verification of the + garbage collector's concurrent mark phase by performing a + second mark pass while the world is stopped. If the second + pass finds a reachable object that was not found by concurrent + mark, the garbage collector will panic. + + gcpacertrace: setting gcpacertrace=1 causes the garbage collector to + print information about the internal state of the concurrent pacer. + + gcshrinkstackoff: setting gcshrinkstackoff=1 disables moving goroutines + onto smaller stacks. In this mode, a goroutine's stack can only grow. + + gcstackbarrieroff: setting gcstackbarrieroff=1 disables the use of stack barriers + that allow the garbage collector to avoid repeating a stack scan during the + mark termination phase. + + gcstoptheworld: setting gcstoptheworld=1 disables concurrent garbage collection, + making every garbage collection a stop-the-world event. Setting gcstoptheworld=2 + also disables concurrent sweeping after the garbage collection finishes. + gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard error at each collection, summarizing the amount of memory collected and the length of the pause. Setting gctrace=2 emits the same summary but also repeats each collection. - gcdead: setting gcdead=1 causes the garbage collector to clobber all stack slots - that it thinks are dead. + memprofilerate: setting memprofilerate=X will update the value of runtime.MemProfileRate. + When set to 0 memory profiling is disabled. Refer to the description of + MemProfileRate for the default value. invalidptr: defaults to invalidptr=1, causing the garbage collector and stack copier to crash the program if an invalid pointer value (for example, 1) @@ -45,9 +66,11 @@ a comma-separated list of name=val pairs. Supported names are: This should only be used as a temporary workaround to diagnose buggy code. The real fix is to not store integers in pointer-typed locations. - memprofilerate: setting memprofilerate=X will update the value of runtime.MemProfileRate. - When set to 0 memory profiling is disabled. Refer to the description of - MemProfileRate for the default value. + sbrk: setting sbrk=1 replaces the memory allocator and garbage collector + with a trivial allocator that obtains memory from the operating system and + never reclaims any memory. + + scavenge: scavenge=1 enables debugging mode of heap scavenger. scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit detailed multiline info every X milliseconds, describing state of the scheduler, @@ -56,14 +79,6 @@ a comma-separated list of name=val pairs. Supported names are: schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard error every X milliseconds, summarizing the scheduler state. - scavenge: scavenge=1 enables debugging mode of heap scavenger. - - gccheckmark: setting gccheckmark=1 enables verification of the - garbage collector's concurrent mark phase by performing a - second mark pass while the world is stopped. If the second - pass finds a reachable object that was not found by concurrent - mark, the garbage collector will panic. - The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously. There is no limit to the number of threads that can be blocked in system calls on behalf of Go code; those do not count against diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 53d6797c52..b7b9ac1323 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -740,6 +740,12 @@ func startGC(mode int) { releasem(mp) mp = nil + if debug.gcstoptheworld == 1 { + mode = gcForceMode + } else if debug.gcstoptheworld == 2 { + mode = gcForceBlockMode + } + if mode != gcBackgroundMode { // special synchronous cases gc(mode) diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index dead22a312..f5fa52dd73 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -327,6 +327,10 @@ func scanstack(gp *g) { barrierOffset = firstStackBarrierOffset nextBarrier = sp + barrierOffset + if debug.gcstackbarrieroff > 0 { + nextBarrier = ^uintptr(0) + } + if gp.stkbarPos != 0 || len(gp.stkbar) != 0 { // If this happens, it's probably because we // scanned a stack twice in the same phase. diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index ea3883018b..e483178d64 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -306,33 +306,37 @@ type dbgVar struct { // existing int var for that value, which may // already have an initial value. var debug struct { - allocfreetrace int32 - efence int32 - gcdead int32 - gctrace int32 - invalidptr int32 - scavenge int32 - scheddetail int32 - schedtrace int32 - wbshadow int32 - gccheckmark int32 - sbrk int32 - gcpacertrace int32 + allocfreetrace int32 + efence int32 + gccheckmark int32 + gcpacertrace int32 + gcshrinkstackoff int32 + gcstackbarrieroff int32 + gcstoptheworld int32 + gctrace int32 + invalidptr int32 + sbrk int32 + scavenge int32 + scheddetail int32 + schedtrace int32 + wbshadow int32 } var dbgvars = []dbgVar{ {"allocfreetrace", &debug.allocfreetrace}, {"efence", &debug.efence}, - {"gcdead", &debug.gcdead}, + {"gccheckmark", &debug.gccheckmark}, + {"gcpacertrace", &debug.gcpacertrace}, + {"gcshrinkstackoff", &debug.gcshrinkstackoff}, + {"gcstackbarrieroff", &debug.gcstackbarrieroff}, + {"gcstoptheworld", &debug.gcstoptheworld}, {"gctrace", &debug.gctrace}, {"invalidptr", &debug.invalidptr}, + {"sbrk", &debug.sbrk}, {"scavenge", &debug.scavenge}, {"scheddetail", &debug.scheddetail}, {"schedtrace", &debug.schedtrace}, {"wbshadow", &debug.wbshadow}, - {"gccheckmark", &debug.gccheckmark}, - {"sbrk", &debug.sbrk}, - {"gcpacertrace", &debug.gcpacertrace}, } func parsedebugvars() { diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go index 1965e9e262..933e3d0b28 100644 --- a/src/runtime/stack1.go +++ b/src/runtime/stack1.go @@ -826,6 +826,10 @@ func shrinkstack(gp *g) { throw("missing stack in shrinkstack") } + if debug.gcshrinkstackoff > 0 { + return + } + oldsize := gp.stackAlloc newsize := oldsize / 2 if newsize < _FixedStack {