]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: do no lose CPU profiling signals
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 13 Aug 2013 18:12:02 +0000 (22:12 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 13 Aug 2013 18:12:02 +0000 (22:12 +0400)
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

src/pkg/runtime/proc.c
src/pkg/runtime/signal_386.c
src/pkg/runtime/signal_amd64.c
src/pkg/runtime/signal_arm.c

index ef4d27f314e995e8bab58da6005a0ef8a49a8728..10a25f0a95b582cdab9fa0b98ae1b78a6b2413b4 100644 (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);
 }
 
index 0d8fc706f139815f04513e15e93d8dbcdd4322a2..0a5b7e543fac797f7f85b626722b7a4d5b71119c 100644 (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;
        }
 
index f566fe16fd45e1b96856bb495265b36d55e99486..a9b204916987e92a5dbf6b5d7621648a81d6b2dd 100644 (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;
        }
 
index febd157891e5988eac5d1cc1e6d861ea1c385f61..0e1740b741a463af917c5dafc117ca2ba9c42df2 100644 (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;
        }