runtime: do no lose CPU profiling signals

Currently we lose lots of profiling signals.
Most notably, GC is not accounted at all.
But stack splits, scheduler, syscalls, etc are lost as well.
This creates seriously misleading profile.
With this change all profiling signals are accounted.
Now I see these additional entries that were previously absent:
161  29.7%  29.7%      164  30.3% syscall.Syscall
 12   2.2%  50.9%       12   2.2% scanblock
 11   2.0%  55.0%       11   2.0% markonly
 10   1.8%  58.9%       10   1.8% sweepspan
  2   0.4%  85.8%        2   0.4% runtime.newstack
It is still impossible to understand what causes stack splits,
but at least it's clear how many time is spent on them.
Update #2197.
Update #5659.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/12179043
This commit is contained in:
Dmitriy Vyukov 2013-08-13 22:12:02 +04:00
parent 1da1030b5d
commit cc4e6aad8e
4 changed files with 28 additions and 12 deletions

View File

@ -1990,26 +1990,45 @@ static struct {
uintptr pcbuf[100];
} prof;
static void
System(void)
{
}
// Called if we receive a SIGPROF signal.
void
runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
{
int32 n;
bool traceback;
// Windows does profiling in a dedicated thread w/o m.
if(!Windows && (m == nil || m->mcache == nil))
return;
if(prof.fn == nil || prof.hz == 0)
return;
traceback = true;
// Windows does profiling in a dedicated thread w/o m.
if(!Windows && (m == nil || m->mcache == nil))
traceback = false;
if(gp == m->g0 || gp == m->gsignal)
traceback = false;
// Race detector calls asmcgocall w/o entersyscall/exitsyscall,
// we can not currently unwind through asmcgocall.
if(m != nil && m->racecall)
traceback = false;
runtime·lock(&prof);
if(prof.fn == nil) {
runtime·unlock(&prof);
return;
}
n = runtime·gentraceback((uintptr)pc, (uintptr)sp, (uintptr)lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false);
if(n > 0)
prof.fn(prof.pcbuf, n);
n = 0;
if(traceback)
n = runtime·gentraceback((uintptr)pc, (uintptr)sp, (uintptr)lr, gp, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false);
if(!traceback || n <= 0) {
n = 2;
prof.pcbuf[0] = (uintptr)pc;
prof.pcbuf[1] = (uintptr)System + 1;
}
prof.fn(prof.pcbuf, n);
runtime·unlock(&prof);
}

View File

@ -39,8 +39,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
bool crash;
if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal)
runtime·sigprof((byte*)SIG_EIP(info, ctxt), (byte*)SIG_ESP(info, ctxt), nil, gp);
runtime·sigprof((byte*)SIG_EIP(info, ctxt), (byte*)SIG_ESP(info, ctxt), nil, gp);
return;
}

View File

@ -47,8 +47,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
bool crash;
if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal)
runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp);
runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp);
return;
}

View File

@ -46,8 +46,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
bool crash;
if(sig == SIGPROF) {
if(gp != m->g0 && gp != m->gsignal)
runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp);
runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp);
return;
}