aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/heapdump.c
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2014-05-08 08:35:49 -0700
committerKeith Randall <khr@golang.org>2014-05-08 08:35:49 -0700
commit65c63dc4aabba3ecd320427fb20bc1cdbe0d2a3d (patch)
tree8773cd3a19ea070f92bbfc3d6a31c818ae20c74e /src/pkg/runtime/heapdump.c
parent1c2cc125fb2baad78167ee543f1d96aea9135734 (diff)
downloadgo-65c63dc4aabba3ecd320427fb20bc1cdbe0d2a3d.tar.xz
runtime: write memory profile statistics to the heap dump.
LGTM=rsc R=rsc, khr CC=golang-codereviews https://golang.org/cl/97010043
Diffstat (limited to 'src/pkg/runtime/heapdump.c')
-rw-r--r--src/pkg/runtime/heapdump.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/pkg/runtime/heapdump.c b/src/pkg/runtime/heapdump.c
index 9132e2c186..42d1601aa1 100644
--- a/src/pkg/runtime/heapdump.c
+++ b/src/pkg/runtime/heapdump.c
@@ -49,6 +49,8 @@ enum {
TagBss = 13,
TagDefer = 14,
TagPanic = 15,
+ TagMemProf = 16,
+ TagAllocSample = 17,
TypeInfo_Conservative = 127,
};
@@ -690,6 +692,74 @@ dumpmemstats(void)
}
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
mdump(G *gp)
{
byte *hdr;
@@ -713,6 +783,7 @@ mdump(G *gp)
dumpms();
dumproots();
dumpmemstats();
+ dumpmemprof();
dumpint(TagEOF);
flush();