mirror of
https://github.com/golang/go
synced 2024-11-19 22:04:44 -07:00
runtime: write memory profile statistics to the heap dump.
LGTM=rsc R=rsc, khr CC=golang-codereviews https://golang.org/cl/97010043
This commit is contained in:
parent
1c2cc125fb
commit
65c63dc4aa
@ -49,6 +49,8 @@ enum {
|
|||||||
TagBss = 13,
|
TagBss = 13,
|
||||||
TagDefer = 14,
|
TagDefer = 14,
|
||||||
TagPanic = 15,
|
TagPanic = 15,
|
||||||
|
TagMemProf = 16,
|
||||||
|
TagAllocSample = 17,
|
||||||
|
|
||||||
TypeInfo_Conservative = 127,
|
TypeInfo_Conservative = 127,
|
||||||
};
|
};
|
||||||
@ -689,6 +691,74 @@ dumpmemstats(void)
|
|||||||
dumpint(mstats.numgc);
|
dumpint(mstats.numgc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dumpmemprof_callback(Bucket *b, uintptr nstk, uintptr *stk, uintptr size, uintptr allocs, uintptr frees)
|
||||||
|
{
|
||||||
|
uintptr i, pc;
|
||||||
|
Func *f;
|
||||||
|
byte buf[20];
|
||||||
|
String file;
|
||||||
|
int32 line;
|
||||||
|
|
||||||
|
dumpint(TagMemProf);
|
||||||
|
dumpint((uintptr)b);
|
||||||
|
dumpint(size);
|
||||||
|
dumpint(nstk);
|
||||||
|
for(i = 0; i < nstk; i++) {
|
||||||
|
pc = stk[i];
|
||||||
|
f = runtime·findfunc(pc);
|
||||||
|
if(f == nil) {
|
||||||
|
runtime·snprintf(buf, sizeof(buf), "%X", (uint64)pc);
|
||||||
|
dumpcstr((int8*)buf);
|
||||||
|
dumpcstr("?");
|
||||||
|
dumpint(0);
|
||||||
|
} else {
|
||||||
|
dumpcstr(runtime·funcname(f));
|
||||||
|
// TODO: Why do we need to back up to a call instruction here?
|
||||||
|
// Maybe profiler should do this.
|
||||||
|
if(i > 0 && pc > f->entry) {
|
||||||
|
if(thechar == '6' || thechar == '8')
|
||||||
|
pc--;
|
||||||
|
else
|
||||||
|
pc -= 4; // arm, etc
|
||||||
|
}
|
||||||
|
line = runtime·funcline(f, pc, &file);
|
||||||
|
dumpstr(file);
|
||||||
|
dumpint(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dumpint(allocs);
|
||||||
|
dumpint(frees);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dumpmemprof(void)
|
||||||
|
{
|
||||||
|
MSpan *s, **allspans;
|
||||||
|
uint32 spanidx;
|
||||||
|
Special *sp;
|
||||||
|
SpecialProfile *spp;
|
||||||
|
byte *p;
|
||||||
|
|
||||||
|
runtime·iterate_memprof(dumpmemprof_callback);
|
||||||
|
|
||||||
|
allspans = runtime·mheap.allspans;
|
||||||
|
for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
|
||||||
|
s = allspans[spanidx];
|
||||||
|
if(s->state != MSpanInUse)
|
||||||
|
continue;
|
||||||
|
for(sp = s->specials; sp != nil; sp = sp->next) {
|
||||||
|
if(sp->kind != KindSpecialProfile)
|
||||||
|
continue;
|
||||||
|
spp = (SpecialProfile*)sp;
|
||||||
|
p = (byte*)((s->start << PageShift) + spp->offset);
|
||||||
|
dumpint(TagAllocSample);
|
||||||
|
dumpint((uintptr)p);
|
||||||
|
dumpint((uintptr)spp->b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mdump(G *gp)
|
mdump(G *gp)
|
||||||
{
|
{
|
||||||
@ -713,6 +783,7 @@ mdump(G *gp)
|
|||||||
dumpms();
|
dumpms();
|
||||||
dumproots();
|
dumproots();
|
||||||
dumpmemstats();
|
dumpmemstats();
|
||||||
|
dumpmemprof();
|
||||||
dumpint(TagEOF);
|
dumpint(TagEOF);
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
|
@ -570,6 +570,7 @@ enum
|
|||||||
void runtime·MProf_Malloc(void*, uintptr);
|
void runtime·MProf_Malloc(void*, uintptr);
|
||||||
void runtime·MProf_Free(Bucket*, uintptr, bool);
|
void runtime·MProf_Free(Bucket*, uintptr, bool);
|
||||||
void runtime·MProf_GC(void);
|
void runtime·MProf_GC(void);
|
||||||
|
void runtime·iterate_memprof(void (*callback)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr));
|
||||||
int32 runtime·gcprocs(void);
|
int32 runtime·gcprocs(void);
|
||||||
void runtime·helpgc(int32 nproc);
|
void runtime·helpgc(int32 nproc);
|
||||||
void runtime·gchelper(void);
|
void runtime·gchelper(void);
|
||||||
|
@ -309,6 +309,18 @@ func MemProfile(p Slice, include_inuse_zero bool) (n int, ok bool) {
|
|||||||
runtime·unlock(&proflock);
|
runtime·unlock(&proflock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
runtime·iterate_memprof(void (*callback)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr))
|
||||||
|
{
|
||||||
|
Bucket *b;
|
||||||
|
|
||||||
|
runtime·lock(&proflock);
|
||||||
|
for(b=mbuckets; b; b=b->allnext) {
|
||||||
|
callback(b, b->nstk, b->stk, b->size, b->allocs, b->frees);
|
||||||
|
}
|
||||||
|
runtime·unlock(&proflock);
|
||||||
|
}
|
||||||
|
|
||||||
// Must match BlockProfileRecord in debug.go.
|
// Must match BlockProfileRecord in debug.go.
|
||||||
typedef struct BRecord BRecord;
|
typedef struct BRecord BRecord;
|
||||||
struct BRecord {
|
struct BRecord {
|
||||||
|
Loading…
Reference in New Issue
Block a user