~ubuntu-branches/ubuntu/utopic/golang/utopic

« back to all changes in this revision

Viewing changes to src/pkg/runtime/pprof/pprof.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
39
40
//
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.
42
43
//
43
44
// The CPU profile is not available as a Profile.  It has a special API,
76
77
        write: writeHeap,
77
78
}
78
79
 
 
80
var blockProfile = &Profile{
 
81
        name:  "block",
 
82
        count: countBlock,
 
83
        write: writeBlock,
 
84
}
 
85
 
79
86
func lockProfiles() {
80
87
        profiles.mu.Lock()
81
88
        if profiles.m == nil {
84
91
                        "goroutine":    goroutineProfile,
85
92
                        "threadcreate": threadcreateProfile,
86
93
                        "heap":         heapProfile,
 
94
                        "block":        blockProfile,
87
95
                }
88
96
        }
89
97
}
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 {
 
321
        wasPanic := false
 
322
        for i, pc := range stk {
314
323
                f := runtime.FuncForPC(pc)
315
324
                if f == nil {
316
325
                        show = true
317
326
                        fmt.Fprintf(w, "#\t%#x\n", pc)
 
327
                        wasPanic = false
318
328
                } else {
319
 
                        file, line := f.FileLine(pc)
 
329
                        tracepc := pc
 
330
                        // Back up to call instruction.
 
331
                        if i > 0 && pc > f.Entry() && !wasPanic {
 
332
                                if runtime.GOARCH == "386" || runtime.GOARCH == "amd64" {
 
333
                                        tracepc--
 
334
                                } else {
 
335
                                        tracepc -= 4 // arm, etc
 
336
                                }
 
337
                        }
 
338
                        file, line := f.FileLine(tracepc)
320
339
                        name := f.Name()
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.") {
324
344
                                continue
325
345
                        }
326
346
                        show = true
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)
328
348
                }
329
349
        }
330
350
        if !show {
352
372
 
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)
356
376
        return n
357
377
}
358
378
 
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)
369
389
        for {
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)
375
395
                if ok {
376
396
                        p = p[0:n]
377
397
                        break
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)
434
455
 
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)
439
462
 
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)
598
621
        <-cpu.done
599
622
}
 
623
 
 
624
type byCycles []runtime.BlockProfileRecord
 
625
 
 
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 }
 
629
 
 
630
// countBlock returns the number of records in the blocking profile.
 
631
func countBlock() int {
 
632
        n, _ := runtime.BlockProfile(nil)
 
633
        return n
 
634
}
 
635
 
 
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)
 
640
        for {
 
641
                p = make([]runtime.BlockProfileRecord, n+50)
 
642
                n, ok = runtime.BlockProfile(p)
 
643
                if ok {
 
644
                        p = p[:n]
 
645
                        break
 
646
                }
 
647
        }
 
648
 
 
649
        sort.Sort(byCycles(p))
 
650
 
 
651
        b := bufio.NewWriter(w)
 
652
        var tw *tabwriter.Writer
 
653
        w = b
 
654
        if debug > 0 {
 
655
                tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
 
656
                w = tw
 
657
        }
 
658
 
 
659
        fmt.Fprintf(w, "--- contention:\n")
 
660
        fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
 
661
        for i := range p {
 
662
                r := &p[i]
 
663
                fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
 
664
                for _, pc := range r.Stack() {
 
665
                        fmt.Fprintf(w, " %#x", pc)
 
666
                }
 
667
                fmt.Fprint(w, "\n")
 
668
                if debug > 0 {
 
669
                        printStackRecord(w, r.Stack(), false)
 
670
                }
 
671
        }
 
672
 
 
673
        if tw != nil {
 
674
                tw.Flush()
 
675
        }
 
676
        return b.Flush()
 
677
}
 
678
 
 
679
func runtime_cyclesPerSecond() int64