"text/template"
)
-// testEnv excludes GOGCTRACE from the environment
+// testEnv excludes GODEBUG from the environment
// to prevent its output from breaking tests that
// are trying to parse other command output.
func testEnv(cmd *exec.Cmd) *exec.Cmd {
panic("environment already set")
}
for _, env := range os.Environ() {
- if strings.HasPrefix(env, "GOGCTRACE=") {
+ if strings.HasPrefix(env, "GODEBUG=") {
continue
}
cmd.Env = append(cmd.Env, env)
The runtime/debug package's SetGCPercent function allows changing this
percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
-The GOGCTRACE variable controls debug output from the garbage collector.
-Setting GOGCTRACE=1 causes the garbage collector to emit a single line to standard
+The GODEBUG variable controls debug output from the runtime. GODEBUG value is
+a comma-separated list of name=val pairs. Supported names are:
+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 GOGCTRACE=2 emits the same summary but also
+length of the pause. Setting gctrace=2 emits the same summary but also
repeats each collection.
The GOMAXPROCS variable limits the number of operating system threads that
//
uint32 runtime·worldsema = 1;
-static int32 gctrace;
-
typedef struct Obj Obj;
struct Obj
{
void
runtime·gc(int32 force)
{
- byte *p;
struct gc_args a;
int32 i;
if(gcpercent == GcpercentUnknown)
gcpercent = readgogc();
runtime·unlock(&runtime·mheap);
-
- p = runtime·getenv("GOGCTRACE");
- if(p != nil)
- gctrace = runtime·atoi(p);
}
if(gcpercent < 0)
return;
// the root set down a bit (g0 stacks are not scanned, and
// we don't need to scan gc's internal state). Also an
// enabler for copyable stacks.
- for(i = 0; i < (gctrace > 1 ? 2 : 1); i++) {
+ for(i = 0; i < (runtime·debug.gctrace > 1 ? 2 : 1); i++) {
if(g == m->g0) {
// already on g0
gc(&a);
heap0 = 0;
obj0 = 0;
- if(gctrace) {
+ if(runtime·debug.gctrace) {
updatememstats(nil);
heap0 = mstats.heap_alloc;
obj0 = mstats.nmalloc - mstats.nfree;
if(mstats.debuggc)
runtime·printf("pause %D\n", t4-t0);
- if(gctrace) {
+ if(runtime·debug.gctrace) {
updatememstats(&stats);
heap1 = mstats.heap_alloc;
obj1 = mstats.nmalloc - mstats.nfree;
uint64 tick, now, forcegc, limit;
uint32 k;
uintptr sumreleased;
- byte *env;
- bool trace;
Note note, *notep;
g->issystem = true;
else
tick = limit/2;
- trace = false;
- env = runtime·getenv("GOGCTRACE");
- if(env != nil)
- trace = runtime·atoi(env) > 0;
-
h = &runtime·mheap;
for(k=0;; k++) {
runtime·noteclear(¬e);
runtime·entersyscallblock();
runtime·notesleep(¬e);
runtime·exitsyscall();
- if(trace)
+ if(runtime·debug.gctrace > 0)
runtime·printf("scvg%d: GC forced\n", k);
runtime·lock(h);
now = runtime·nanotime();
sumreleased = scavenge(now, limit);
runtime·unlock(h);
- if(trace) {
+ if(runtime·debug.gctrace > 0) {
if(sumreleased > 0)
runtime·printf("scvg%d: %p MB released\n", k, sumreleased>>20);
runtime·printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
runtime·goargs();
runtime·goenvs();
+ runtime·parsedebugvars();
// Allocate internal symbol table representation now, we need it for GC anyway.
runtime·symtabinit();
// It is required because the tests contain a lot of data races on the same addresses
// (the tests are simple and the memory is constantly reused).
for _, env := range os.Environ() {
- if strings.HasPrefix(env, "GOMAXPROCS=") || strings.HasPrefix(env, "GOGCTRACE=") {
+ if strings.HasPrefix(env, "GOMAXPROCS=") || strings.HasPrefix(env, "GODEBUG=") {
continue
}
cmd.Env = append(cmd.Env, env)
res = runtime·tickspersecond();
FLUSH(&res);
}
+
+DebugVars runtime·debug;
+
+static struct {
+ int8* name;
+ int32* value;
+} dbgvar[] = {
+ {"gctrace", &runtime·debug.gctrace},
+};
+
+void
+runtime·parsedebugvars(void)
+{
+ byte *p;
+ int32 i, n;
+
+ p = runtime·getenv("GODEBUG");
+ if(p == nil)
+ return;
+ for(;;) {
+ for(i=0; i<nelem(dbgvar); i++) {
+ n = runtime·findnull((byte*)dbgvar[i].name);
+ if(runtime·mcmp(p, (byte*)dbgvar[i].name, n) == 0 && p[n] == '=')
+ *dbgvar[i].value = runtime·atoi(p+n+1);
+ }
+ p = runtime·strstr(p, (byte*)",");
+ if(p == nil)
+ break;
+ p++;
+ }
+}
typedef struct ParForThread ParForThread;
typedef struct CgoMal CgoMal;
typedef struct PollDesc PollDesc;
+typedef struct DebugVars DebugVars;
/*
* Per-CPU declaration.
void *alloc;
};
+// Holds variables parsed from GODEBUG env var.
+struct DebugVars
+{
+ int32 gctrace;
+};
+
/*
* defined macros
* you need super-gopher-guru privilege
extern uint32 runtime·Hchansize;
extern uint32 runtime·cpuid_ecx;
extern uint32 runtime·cpuid_edx;
+extern DebugVars runtime·debug;
/*
* common functions and data
int32 runtime·netpollclose(uintptr);
void runtime·netpollready(G**, PollDesc*, int32);
void runtime·crash(void);
+void runtime·parsedebugvars(void);
void _rt0_go(void);
#pragma varargck argpos runtime·printf 1