mirror of
https://github.com/golang/go
synced 2024-11-18 15:04:44 -07:00
runtime: introduce GODEBUG env var
Currently it replaces GOGCTRACE env var (GODEBUG=gctrace=1). The plan is to extend it with other type of debug tracing, e.g. GODEBUG=gctrace=1,schedtrace=100. R=rsc CC=bradfitz, daniel.morsing, gobot, golang-dev https://golang.org/cl/10026045
This commit is contained in:
parent
1e112cd59f
commit
4b536a550f
@ -14,7 +14,7 @@ import (
|
||||
"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 {
|
||||
@ -22,7 +22,7 @@ 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)
|
||||
|
@ -21,10 +21,11 @@ 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 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
|
||||
|
@ -82,8 +82,6 @@ enum {
|
||||
//
|
||||
uint32 runtime·worldsema = 1;
|
||||
|
||||
static int32 gctrace;
|
||||
|
||||
typedef struct Obj Obj;
|
||||
struct Obj
|
||||
{
|
||||
@ -1950,7 +1948,6 @@ static FuncVal runfinqv = {runfinq};
|
||||
void
|
||||
runtime·gc(int32 force)
|
||||
{
|
||||
byte *p;
|
||||
struct gc_args a;
|
||||
int32 i;
|
||||
|
||||
@ -1978,10 +1975,6 @@ runtime·gc(int32 force)
|
||||
if(gcpercent == GcpercentUnknown)
|
||||
gcpercent = readgogc();
|
||||
runtime·unlock(&runtime·mheap);
|
||||
|
||||
p = runtime·getenv("GOGCTRACE");
|
||||
if(p != nil)
|
||||
gctrace = runtime·atoi(p);
|
||||
}
|
||||
if(gcpercent < 0)
|
||||
return;
|
||||
@ -2004,7 +1997,7 @@ runtime·gc(int32 force)
|
||||
// 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);
|
||||
@ -2068,7 +2061,7 @@ gc(struct gc_args *args)
|
||||
|
||||
heap0 = 0;
|
||||
obj0 = 0;
|
||||
if(gctrace) {
|
||||
if(runtime·debug.gctrace) {
|
||||
updatememstats(nil);
|
||||
heap0 = mstats.heap_alloc;
|
||||
obj0 = mstats.nmalloc - mstats.nfree;
|
||||
@ -2131,7 +2124,7 @@ gc(struct gc_args *args)
|
||||
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;
|
||||
|
@ -441,8 +441,6 @@ runtime·MHeap_Scavenger(void)
|
||||
uint64 tick, now, forcegc, limit;
|
||||
uint32 k;
|
||||
uintptr sumreleased;
|
||||
byte *env;
|
||||
bool trace;
|
||||
Note note, *notep;
|
||||
|
||||
g->issystem = true;
|
||||
@ -459,11 +457,6 @@ runtime·MHeap_Scavenger(void)
|
||||
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);
|
||||
@ -484,7 +477,7 @@ runtime·MHeap_Scavenger(void)
|
||||
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();
|
||||
@ -492,7 +485,7 @@ runtime·MHeap_Scavenger(void)
|
||||
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",
|
||||
|
@ -132,6 +132,7 @@ runtime·schedinit(void)
|
||||
|
||||
runtime·goargs();
|
||||
runtime·goenvs();
|
||||
runtime·parsedebugvars();
|
||||
|
||||
// Allocate internal symbol table representation now, we need it for GC anyway.
|
||||
runtime·symtabinit();
|
||||
|
@ -147,7 +147,7 @@ func runTests() ([]byte, error) {
|
||||
// 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)
|
||||
|
@ -365,3 +365,34 @@ runtime∕pprof·runtime_cyclesPerSecond(int64 res)
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ typedef struct ParFor ParFor;
|
||||
typedef struct ParForThread ParForThread;
|
||||
typedef struct CgoMal CgoMal;
|
||||
typedef struct PollDesc PollDesc;
|
||||
typedef struct DebugVars DebugVars;
|
||||
|
||||
/*
|
||||
* Per-CPU declaration.
|
||||
@ -525,6 +526,12 @@ struct CgoMal
|
||||
void *alloc;
|
||||
};
|
||||
|
||||
// Holds variables parsed from GODEBUG env var.
|
||||
struct DebugVars
|
||||
{
|
||||
int32 gctrace;
|
||||
};
|
||||
|
||||
/*
|
||||
* defined macros
|
||||
* you need super-gopher-guru privilege
|
||||
@ -702,6 +709,7 @@ extern uint32 runtime·maxstring;
|
||||
extern uint32 runtime·Hchansize;
|
||||
extern uint32 runtime·cpuid_ecx;
|
||||
extern uint32 runtime·cpuid_edx;
|
||||
extern DebugVars runtime·debug;
|
||||
|
||||
/*
|
||||
* common functions and data
|
||||
@ -841,6 +849,7 @@ int32 runtime·netpollopen(uintptr, PollDesc*);
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user