1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package pprof writes runtime profiling data in the format expected
6 // by the pprof visualization tool.
7 // For more information about pprof, see
8 // http://code.google.com/p/google-perftools/.
19 // WriteHeapProfile writes a pprof-formatted heap profile to w.
20 // If a write to w returns an error, WriteHeapProfile returns that error.
21 // Otherwise, WriteHeapProfile returns nil.
22 func WriteHeapProfile(w io.Writer) os.Error {
23 // Find out how many records there are (MemProfile(nil, false)),
24 // allocate that many records, and get the data.
25 // There's a race—more records might be added between
26 // the two calls—so allocate a few extra records for safety
27 // and also try again if we're very unlucky.
28 // The loop should only execute one iteration in the common case.
29 var p []runtime.MemProfileRecord
30 n, ok := runtime.MemProfile(nil, false)
32 // Allocate room for a slightly bigger profile,
33 // in case a few more entries have been added
34 // since the call to MemProfile.
35 p = make([]runtime.MemProfileRecord, n+50)
36 n, ok = runtime.MemProfile(p, false)
41 // Profile grew; try again.
44 var total runtime.MemProfileRecord
47 total.AllocBytes += r.AllocBytes
48 total.AllocObjects += r.AllocObjects
49 total.FreeBytes += r.FreeBytes
50 total.FreeObjects += r.FreeObjects
53 // Technically the rate is MemProfileRate not 2*MemProfileRate,
54 // but early versions of the C++ heap profiler reported 2*MemProfileRate,
55 // so that's what pprof has come to expect.
56 b := bufio.NewWriter(w)
57 fmt.Fprintf(b, "heap profile: %d: %d [%d: %d] @ heap/%d\n",
58 total.InUseObjects(), total.InUseBytes(),
59 total.AllocObjects, total.AllocBytes,
60 2*runtime.MemProfileRate)
64 fmt.Fprintf(b, "%d: %d [%d: %d] @",
65 r.InUseObjects(), r.InUseBytes(),
66 r.AllocObjects, r.AllocBytes)
67 for _, pc := range r.Stack() {
68 fmt.Fprintf(b, " %#x", pc)
73 // Print memstats information too.
74 // Pprof will ignore, but useful for people.
75 s := &runtime.MemStats
76 fmt.Fprintf(b, "\n# runtime.MemStats\n")
77 fmt.Fprintf(b, "# Alloc = %d\n", s.Alloc)
78 fmt.Fprintf(b, "# TotalAlloc = %d\n", s.TotalAlloc)
79 fmt.Fprintf(b, "# Sys = %d\n", s.Sys)
80 fmt.Fprintf(b, "# Lookups = %d\n", s.Lookups)
81 fmt.Fprintf(b, "# Mallocs = %d\n", s.Mallocs)
83 fmt.Fprintf(b, "# HeapAlloc = %d\n", s.HeapAlloc)
84 fmt.Fprintf(b, "# HeapSys = %d\n", s.HeapSys)
85 fmt.Fprintf(b, "# HeapIdle = %d\n", s.HeapIdle)
86 fmt.Fprintf(b, "# HeapInuse = %d\n", s.HeapInuse)
88 fmt.Fprintf(b, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
89 fmt.Fprintf(b, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
90 fmt.Fprintf(b, "# MCache = %d / %d\n", s.MCacheInuse, s.MCacheSys)
91 fmt.Fprintf(b, "# BuckHashSys = %d\n", s.BuckHashSys)
93 fmt.Fprintf(b, "# NextGC = %d\n", s.NextGC)
94 fmt.Fprintf(b, "# PauseNs = %d\n", s.PauseNs)
95 fmt.Fprintf(b, "# NumGC = %d\n", s.NumGC)
96 fmt.Fprintf(b, "# EnableGC = %v\n", s.EnableGC)
97 fmt.Fprintf(b, "# DebugGC = %v\n", s.DebugGC)
99 fmt.Fprintf(b, "# BySize = Size * (Active = Mallocs - Frees)\n")
100 fmt.Fprintf(b, "# (Excluding large blocks.)\n")
101 for _, t := range s.BySize {
103 fmt.Fprintf(b, "# %d * (%d = %d - %d)\n", t.Size, t.Mallocs-t.Frees, t.Mallocs, t.Frees)