diff options
| author | Dmitriy Vyukov <dvyukov@google.com> | 2014-02-12 22:31:36 +0400 |
|---|---|---|
| committer | Dmitriy Vyukov <dvyukov@google.com> | 2014-02-12 22:31:36 +0400 |
| commit | 5e72fae9b2c4fddc67a5d8ea0aecf3f73234d83e (patch) | |
| tree | d6550eeae7533146e462eb2e350e9455c0c6e2d0 /src/pkg/runtime/proc.c | |
| parent | 44c252bda29585b4ee9f18e77e68c658207e6f0a (diff) | |
| download | go-5e72fae9b2c4fddc67a5d8ea0aecf3f73234d83e.tar.xz | |
runtime: improve cpu profiles for GC/syscalls/cgo
Current "System->etext" is not very informative.
Add parent "GC" frame.
Replace un-unwindable syscall/cgo frames with Go stack that leads to the call.
LGTM=rsc
R=rsc, alex.brainman, ality
CC=golang-codereviews
https://golang.org/cl/61270043
Diffstat (limited to 'src/pkg/runtime/proc.c')
| -rw-r--r-- | src/pkg/runtime/proc.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index c771d5f916..88d6acead3 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -2104,10 +2104,10 @@ static struct { uintptr pcbuf[100]; } prof; -static void -System(void) -{ -} +static void System(void) {} +static void ExternalCode(void) {} +static void GC(void) {} +extern byte etext[]; // Called if we receive a SIGPROF signal. void @@ -2221,9 +2221,35 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp) 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; + // Normal traceback is impossible or has failed. + // See if it falls into several common cases. + n = 0; + if(mp->ncgo > 0 && mp->curg != nil && + mp->curg->syscallpc != 0 && mp->curg->syscallsp != 0) { + // Cgo, we can't unwind and symbolize arbitrary C code, + // so instead collect Go stack that leads to the cgo call. + // This is especially important on windows, since all syscalls are cgo calls. + n = runtime·gentraceback(mp->curg->syscallpc, mp->curg->syscallsp, 0, mp->curg, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false); + } +#ifdef GOOS_windows + if(n == 0 && mp->libcallg != nil && mp->libcallpc != 0 && mp->libcallsp != 0) { + // Libcall, i.e. runtime syscall on windows. + // Collect Go stack that leads to the call. + n = runtime·gentraceback(mp->libcallpc, mp->libcallsp, 0, mp->libcallg, 0, prof.pcbuf, nelem(prof.pcbuf), nil, nil, false); + } +#endif + if(n == 0) { + // If all of the above has failed, account it against abstract "System" or "GC". + n = 2; + // "ExternalCode" is better than "etext". + if((uintptr)pc > (uintptr)etext) + pc = (byte*)ExternalCode + PCQuantum; + prof.pcbuf[0] = (uintptr)pc; + if(mp->gcing || mp->helpgc) + prof.pcbuf[1] = (uintptr)GC + PCQuantum; + else + prof.pcbuf[1] = (uintptr)System + PCQuantum; + } } prof.fn(prof.pcbuf, n); runtime·unlock(&prof); |
