36
36
// goroutine - stack traces of all current goroutines
37
37
// heap - a sampling of all heap allocations
38
38
// threadcreate - stack traces that led to the creation of new OS threads
39
// block - stack traces that led to blocking on synchronization primitives
40
// These predefine profiles maintain themselves and panic on an explicit
41
// These predefined profiles maintain themselves and panic on an explicit
41
42
// Add or Remove method call.
43
44
// The CPU profile is not available as a Profile. It has a special API,
310
318
// for a single stack trace.
311
319
func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
312
320
show := allFrames
313
for _, pc := range stk {
322
for i, pc := range stk {
314
323
f := runtime.FuncForPC(pc)
317
326
fmt.Fprintf(w, "#\t%#x\n", pc)
319
file, line := f.FileLine(pc)
330
// Back up to call instruction.
331
if i > 0 && pc > f.Entry() && !wasPanic {
332
if runtime.GOARCH == "386" || runtime.GOARCH == "amd64" {
335
tracepc -= 4 // arm, etc
338
file, line := f.FileLine(tracepc)
321
340
// Hide runtime.goexit and any runtime functions at the beginning.
322
341
// This is useful mainly for allocation traces.
342
wasPanic = name == "runtime.panic"
323
343
if name == "runtime.goexit" || !show && strings.HasPrefix(name, "runtime.") {
327
fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", pc, f.Name(), pc-f.Entry(), file, line)
347
fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", pc, name, pc-f.Entry(), file, line)
353
373
// countHeap returns the number of records in the heap profile.
354
374
func countHeap() int {
355
n, _ := runtime.MemProfile(nil, false)
375
n, _ := runtime.MemProfile(nil, true)
359
// writeHeapProfile writes the current runtime heap profile to w.
379
// writeHeap writes the current runtime heap profile to w.
360
380
func writeHeap(w io.Writer, debug int) error {
361
// Find out how many records there are (MemProfile(nil, false)),
381
// Find out how many records there are (MemProfile(nil, true)),
362
382
// allocate that many records, and get the data.
363
383
// There's a race—more records might be added between
364
384
// the two calls—so allocate a few extra records for safety
365
385
// and also try again if we're very unlucky.
366
386
// The loop should only execute one iteration in the common case.
367
387
var p []runtime.MemProfileRecord
368
n, ok := runtime.MemProfile(nil, false)
388
n, ok := runtime.MemProfile(nil, true)
370
390
// Allocate room for a slightly bigger profile,
371
391
// in case a few more entries have been added
372
392
// since the call to MemProfile.
373
393
p = make([]runtime.MemProfileRecord, n+50)
374
n, ok = runtime.MemProfile(p, false)
394
n, ok = runtime.MemProfile(p, true)
431
451
fmt.Fprintf(w, "# Sys = %d\n", s.Sys)
432
452
fmt.Fprintf(w, "# Lookups = %d\n", s.Lookups)
433
453
fmt.Fprintf(w, "# Mallocs = %d\n", s.Mallocs)
454
fmt.Fprintf(w, "# Frees = %d\n", s.Frees)
435
456
fmt.Fprintf(w, "# HeapAlloc = %d\n", s.HeapAlloc)
436
457
fmt.Fprintf(w, "# HeapSys = %d\n", s.HeapSys)
437
458
fmt.Fprintf(w, "# HeapIdle = %d\n", s.HeapIdle)
438
459
fmt.Fprintf(w, "# HeapInuse = %d\n", s.HeapInuse)
460
fmt.Fprintf(w, "# HeapReleased = %d\n", s.HeapReleased)
461
fmt.Fprintf(w, "# HeapObjects = %d\n", s.HeapObjects)
440
463
fmt.Fprintf(w, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
441
464
fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
597
620
runtime.SetCPUProfileRate(0)
624
type byCycles []runtime.BlockProfileRecord
626
func (x byCycles) Len() int { return len(x) }
627
func (x byCycles) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
628
func (x byCycles) Less(i, j int) bool { return x[i].Cycles > x[j].Cycles }
630
// countBlock returns the number of records in the blocking profile.
631
func countBlock() int {
632
n, _ := runtime.BlockProfile(nil)
636
// writeBlock writes the current blocking profile to w.
637
func writeBlock(w io.Writer, debug int) error {
638
var p []runtime.BlockProfileRecord
639
n, ok := runtime.BlockProfile(nil)
641
p = make([]runtime.BlockProfileRecord, n+50)
642
n, ok = runtime.BlockProfile(p)
649
sort.Sort(byCycles(p))
651
b := bufio.NewWriter(w)
652
var tw *tabwriter.Writer
655
tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
659
fmt.Fprintf(w, "--- contention:\n")
660
fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
663
fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
664
for _, pc := range r.Stack() {
665
fmt.Fprintf(w, " %#x", pc)
669
printStackRecord(w, r.Stack(), false)
679
func runtime_cyclesPerSecond() int64