summaryrefslogtreecommitdiff
path: root/devdocs/go/runtime%2Fpprof%2Findex.html
blob: 1d4391d79e17b9bfa185fe1133c15c489c11c069 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<h1> Package pprof  </h1>     <ul id="short-nav">
<li><code>import "runtime/pprof"</code></li>
<li><a href="#pkg-overview" class="overviewLink">Overview</a></li>
<li><a href="#pkg-index" class="indexLink">Index</a></li>
</ul>     <h2 id="pkg-overview">Overview </h2> <p>Package pprof writes runtime profiling data in the format expected by the pprof visualization tool. </p>
<h3 id="hdr-Profiling_a_Go_program">Profiling a Go program</h3> <p>The first step to profiling a Go program is to enable profiling. Support for profiling benchmarks built with the standard testing package is built into go test. For example, the following command runs benchmarks in the current directory and writes the CPU and memory profiles to cpu.prof and mem.prof: </p>
<pre data-language="go">go test -cpuprofile cpu.prof -memprofile mem.prof -bench .
</pre> <p>To add equivalent profiling support to a standalone program, add code like the following to your main function: </p>
<pre data-language="go">var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")

func main() {
    flag.Parse()
    if *cpuprofile != "" {
        f, err := os.Create(*cpuprofile)
        if err != nil {
            log.Fatal("could not create CPU profile: ", err)
        }
        defer f.Close() // error handling omitted for example
        if err := pprof.StartCPUProfile(f); err != nil {
            log.Fatal("could not start CPU profile: ", err)
        }
        defer pprof.StopCPUProfile()
    }

    // ... rest of the program ...

    if *memprofile != "" {
        f, err := os.Create(*memprofile)
        if err != nil {
            log.Fatal("could not create memory profile: ", err)
        }
        defer f.Close() // error handling omitted for example
        runtime.GC() // get up-to-date statistics
        if err := pprof.WriteHeapProfile(f); err != nil {
            log.Fatal("could not write memory profile: ", err)
        }
    }
}
</pre> <p>There is also a standard HTTP interface to profiling data. Adding the following line will install handlers under the /debug/pprof/ URL to download live profiles: </p>
<pre data-language="go">import _ "net/http/pprof"
</pre> <p>See the net/http/pprof package for more details. </p>
<p>Profiles can then be visualized with the pprof tool: </p>
<pre data-language="go">go tool pprof cpu.prof
</pre> <p>There are many commands available from the pprof command line. Commonly used commands include "top", which prints a summary of the top program hot-spots, and "web", which opens an interactive graph of hot-spots and their call graphs. Use "help" for information on all pprof commands. </p>
<p>For more information about pprof, see <a href="https://github.com/google/pprof/blob/main/doc/README.md">https://github.com/google/pprof/blob/main/doc/README.md</a>. </p>     <h2 id="pkg-index">Index </h2>  <ul id="manual-nav">
<li><a href="#Do">func Do(ctx context.Context, labels LabelSet, f func(context.Context))</a></li>
<li><a href="#ForLabels">func ForLabels(ctx context.Context, f func(key, value string) bool)</a></li>
<li><a href="#Label">func Label(ctx context.Context, key string) (string, bool)</a></li>
<li><a href="#SetGoroutineLabels">func SetGoroutineLabels(ctx context.Context)</a></li>
<li><a href="#StartCPUProfile">func StartCPUProfile(w io.Writer) error</a></li>
<li><a href="#StopCPUProfile">func StopCPUProfile()</a></li>
<li><a href="#WithLabels">func WithLabels(ctx context.Context, labels LabelSet) context.Context</a></li>
<li><a href="#WriteHeapProfile">func WriteHeapProfile(w io.Writer) error</a></li>
<li><a href="#LabelSet">type LabelSet</a></li>
<li> <a href="#Labels">func Labels(args ...string) LabelSet</a>
</li>
<li><a href="#Profile">type Profile</a></li>
<li> <a href="#Lookup">func Lookup(name string) *Profile</a>
</li>
<li> <a href="#NewProfile">func NewProfile(name string) *Profile</a>
</li>
<li> <a href="#Profiles">func Profiles() []*Profile</a>
</li>
<li> <a href="#Profile.Add">func (p *Profile) Add(value any, skip int)</a>
</li>
<li> <a href="#Profile.Count">func (p *Profile) Count() int</a>
</li>
<li> <a href="#Profile.Name">func (p *Profile) Name() string</a>
</li>
<li> <a href="#Profile.Remove">func (p *Profile) Remove(value any)</a>
</li>
<li> <a href="#Profile.WriteTo">func (p *Profile) WriteTo(w io.Writer, debug int) error</a>
</li>
<li><a href="#pkg-note-BUG">Bugs</a></li>
</ul> <h3>Package files</h3> <p>  <span>elf.go</span> <span>label.go</span> <span>map.go</span> <span>pe.go</span> <span>pprof.go</span> <span>pprof_rusage.go</span> <span>proto.go</span> <span>proto_other.go</span> <span>protobuf.go</span> <span>protomem.go</span> <span>runtime.go</span>  </p>   <h2 id="Do">func <span>Do</span>  <span title="Added in Go 1.9">1.9</span> </h2> <pre data-language="go">func Do(ctx context.Context, labels LabelSet, f func(context.Context))</pre> <p>Do calls f with a copy of the parent context with the given labels added to the parent's label map. Goroutines spawned while executing f will inherit the augmented label-set. Each key/value pair in labels is inserted into the label map in the order provided, overriding any previous value for the same key. The augmented label map will be set for the duration of the call to f and restored once f returns. </p>
<h2 id="ForLabels">func <span>ForLabels</span>  <span title="Added in Go 1.9">1.9</span> </h2> <pre data-language="go">func ForLabels(ctx context.Context, f func(key, value string) bool)</pre> <p>ForLabels invokes f with each label set on the context. The function f should return true to continue iteration or false to stop iteration early. </p>
<h2 id="Label">func <span>Label</span>  <span title="Added in Go 1.9">1.9</span> </h2> <pre data-language="go">func Label(ctx context.Context, key string) (string, bool)</pre> <p>Label returns the value of the label with the given key on ctx, and a boolean indicating whether that label exists. </p>
<h2 id="SetGoroutineLabels">func <span>SetGoroutineLabels</span>  <span title="Added in Go 1.9">1.9</span> </h2> <pre data-language="go">func SetGoroutineLabels(ctx context.Context)</pre> <p>SetGoroutineLabels sets the current goroutine's labels to match ctx. A new goroutine inherits the labels of the goroutine that created it. This is a lower-level API than <a href="#Do">Do</a>, which should be used instead when possible. </p>
<h2 id="StartCPUProfile">func <span>StartCPUProfile</span>  </h2> <pre data-language="go">func StartCPUProfile(w io.Writer) error</pre> <p>StartCPUProfile enables CPU profiling for the current process. While profiling, the profile will be buffered and written to w. StartCPUProfile returns an error if profiling is already enabled. </p>
<p>On Unix-like systems, StartCPUProfile does not work by default for Go code built with -buildmode=c-archive or -buildmode=c-shared. StartCPUProfile relies on the SIGPROF signal, but that signal will be delivered to the main program's SIGPROF signal handler (if any) not to the one used by Go. To make it work, call <span>os/signal.Notify</span> for <span>syscall.SIGPROF</span>, but note that doing so may break any profiling being done by the main program. </p>
<h2 id="StopCPUProfile">func <span>StopCPUProfile</span>  </h2> <pre data-language="go">func StopCPUProfile()</pre> <p>StopCPUProfile stops the current CPU profile, if any. StopCPUProfile only returns after all the writes for the profile have completed. </p>
<h2 id="WithLabels">func <span>WithLabels</span>  <span title="Added in Go 1.9">1.9</span> </h2> <pre data-language="go">func WithLabels(ctx context.Context, labels LabelSet) context.Context</pre> <p>WithLabels returns a new <span>context.Context</span> with the given labels added. A label overwrites a prior label with the same key. </p>
<h2 id="WriteHeapProfile">func <span>WriteHeapProfile</span>  </h2> <pre data-language="go">func WriteHeapProfile(w io.Writer) error</pre> <p>WriteHeapProfile is shorthand for <a href="#Lookup">Lookup</a>("heap").WriteTo(w, 0). It is preserved for backwards compatibility. </p>
<h2 id="LabelSet">type <span>LabelSet</span>  <span title="Added in Go 1.9">1.9</span> </h2> <p>LabelSet is a set of labels. </p>
<pre data-language="go">type LabelSet struct {
    // contains filtered or unexported fields
}
</pre> <h3 id="Labels">func <span>Labels</span>  <span title="Added in Go 1.9">1.9</span> </h3> <pre data-language="go">func Labels(args ...string) LabelSet</pre> <p>Labels takes an even number of strings representing key-value pairs and makes a <a href="#LabelSet">LabelSet</a> containing them. A label overwrites a prior label with the same key. Currently only the CPU and goroutine profiles utilize any labels information. See <a href="https://golang.org/issue/23458">https://golang.org/issue/23458</a> for details. </p>
<h2 id="Profile">type <span>Profile</span>  </h2> <p>A Profile is a collection of stack traces showing the call sequences that led to instances of a particular event, such as allocation. Packages can create and maintain their own profiles; the most common use is for tracking resources that must be explicitly closed, such as files or network connections. </p>
<p>A Profile's methods can be called from multiple goroutines simultaneously. </p>
<p>Each Profile has a unique name. A few profiles are predefined: </p>
<pre data-language="go">goroutine    - stack traces of all current goroutines
heap         - a sampling of memory allocations of live objects
allocs       - a sampling of all past memory allocations
threadcreate - stack traces that led to the creation of new OS threads
block        - stack traces that led to blocking on synchronization primitives
mutex        - stack traces of holders of contended mutexes
</pre> <p>These predefined profiles maintain themselves and panic on an explicit <a href="#Profile.Add">Profile.Add</a> or <a href="#Profile.Remove">Profile.Remove</a> method call. </p>
<p>The CPU profile is not available as a Profile. It has a special API, the <a href="#StartCPUProfile">StartCPUProfile</a> and <a href="#StopCPUProfile">StopCPUProfile</a> functions, because it streams output to a writer during profiling. </p>
<h3 id="hdr-Heap_profile">Heap profile</h3> <p>The heap profile reports statistics as of the most recently completed garbage collection; it elides more recent allocation to avoid skewing the profile away from live data and toward garbage. If there has been no garbage collection at all, the heap profile reports all known allocations. This exception helps mainly in programs running without garbage collection enabled, usually for debugging purposes. </p>
<p>The heap profile tracks both the allocation sites for all live objects in the application memory and for all objects allocated since the program start. Pprof's -inuse_space, -inuse_objects, -alloc_space, and -alloc_objects flags select which to display, defaulting to -inuse_space (live objects, scaled by size). </p>
<h3 id="hdr-Allocs_profile">Allocs profile</h3> <p>The allocs profile is the same as the heap profile but changes the default pprof display to -alloc_space, the total number of bytes allocated since the program began (including garbage-collected bytes). </p>
<h3 id="hdr-Block_profile">Block profile</h3> <p>The block profile tracks time spent blocked on synchronization primitives, such as <span>sync.Mutex</span>, <span>sync.RWMutex</span>, <span>sync.WaitGroup</span>, <span>sync.Cond</span>, and channel send/receive/select. </p>
<p>Stack traces correspond to the location that blocked (for example, <span>sync.Mutex.Lock</span>). </p>
<p>Sample values correspond to cumulative time spent blocked at that stack trace, subject to time-based sampling specified by <span>runtime.SetBlockProfileRate</span>. </p>
<h3 id="hdr-Mutex_profile">Mutex profile</h3> <p>The mutex profile tracks contention on mutexes, such as <span>sync.Mutex</span>, <span>sync.RWMutex</span>, and runtime-internal locks. </p>
<p>Stack traces correspond to the end of the critical section causing contention. For example, a lock held for a long time while other goroutines are waiting to acquire the lock will report contention when the lock is finally unlocked (that is, at <span>sync.Mutex.Unlock</span>). </p>
<p>Sample values correspond to the approximate cumulative time other goroutines spent blocked waiting for the lock, subject to event-based sampling specified by <span>runtime.SetMutexProfileFraction</span>. For example, if a caller holds a lock for 1s while 5 other goroutines are waiting for the entire second to acquire the lock, its unlock call stack will report 5s of contention. </p>
<p>Runtime-internal locks are always reported at the location "runtime._LostContendedRuntimeLock". More detailed stack traces for runtime-internal locks can be obtained by setting `GODEBUG=runtimecontentionstacks=1` (see package <span>runtime</span> docs for caveats). </p>
<pre data-language="go">type Profile struct {
    // contains filtered or unexported fields
}
</pre> <h3 id="Lookup">func <span>Lookup</span>  </h3> <pre data-language="go">func Lookup(name string) *Profile</pre> <p>Lookup returns the profile with the given name, or nil if no such profile exists. </p>
<h3 id="NewProfile">func <span>NewProfile</span>  </h3> <pre data-language="go">func NewProfile(name string) *Profile</pre> <p>NewProfile creates a new profile with the given name. If a profile with that name already exists, NewProfile panics. The convention is to use a 'import/path.' prefix to create separate name spaces for each package. For compatibility with various tools that read pprof data, profile names should not contain spaces. </p>
<h3 id="Profiles">func <span>Profiles</span>  </h3> <pre data-language="go">func Profiles() []*Profile</pre> <p>Profiles returns a slice of all the known profiles, sorted by name. </p>
<h3 id="Profile.Add">func (*Profile) <span>Add</span>  </h3> <pre data-language="go">func (p *Profile) Add(value any, skip int)</pre> <p>Add adds the current execution stack to the profile, associated with value. Add stores value in an internal map, so value must be suitable for use as a map key and will not be garbage collected until the corresponding call to <a href="#Profile.Remove">Profile.Remove</a>. Add panics if the profile already contains a stack for value. </p>
<p>The skip parameter has the same meaning as <span>runtime.Caller</span>'s skip and controls where the stack trace begins. Passing skip=0 begins the trace in the function calling Add. For example, given this execution stack: </p>
<pre data-language="go">Add
called from rpc.NewClient
called from mypkg.Run
called from main.main
</pre> <p>Passing skip=0 begins the stack trace at the call to Add inside rpc.NewClient. Passing skip=1 begins the stack trace at the call to NewClient inside mypkg.Run. </p>
<h3 id="Profile.Count">func (*Profile) <span>Count</span>  </h3> <pre data-language="go">func (p *Profile) Count() int</pre> <p>Count returns the number of execution stacks currently in the profile. </p>
<h3 id="Profile.Name">func (*Profile) <span>Name</span>  </h3> <pre data-language="go">func (p *Profile) Name() string</pre> <p>Name returns this profile's name, which can be passed to <a href="#Lookup">Lookup</a> to reobtain the profile. </p>
<h3 id="Profile.Remove">func (*Profile) <span>Remove</span>  </h3> <pre data-language="go">func (p *Profile) Remove(value any)</pre> <p>Remove removes the execution stack associated with value from the profile. It is a no-op if the value is not in the profile. </p>
<h3 id="Profile.WriteTo">func (*Profile) <span>WriteTo</span>  </h3> <pre data-language="go">func (p *Profile) WriteTo(w io.Writer, debug int) error</pre> <p>WriteTo writes a pprof-formatted snapshot of the profile to w. If a write to w returns an error, WriteTo returns that error. Otherwise, WriteTo returns nil. </p>
<p>The debug parameter enables additional output. Passing debug=0 writes the gzip-compressed protocol buffer described in <a href="https://github.com/google/pprof/tree/master/proto#overview">https://github.com/google/pprof/tree/master/proto#overview</a>. Passing debug=1 writes the legacy text format with comments translating addresses to function names and line numbers, so that a programmer can read the profile without tools. </p>
<p>The predefined profiles may assign meaning to other debug values; for example, when printing the "goroutine" profile, debug=2 means to print the goroutine stacks in the same form that a Go program uses when dying due to an unrecovered panic. </p>
<h2 id="pkg-note-BUG">Bugs</h2> <ul> <li>☞ <p>Profiles are only as good as the kernel support used to generate them. See <a href="https://golang.org/issue/13841">https://golang.org/issue/13841</a> for details about known problems. </p>
</li> </ul><div class="_attribution">
  <p class="_attribution-p">
    &copy; Google, Inc.<br>Licensed under the Creative Commons Attribution License 3.0.<br>
    <a href="http://golang.org/pkg/runtime/pprof/" class="_attribution-link">http://golang.org/pkg/runtime/pprof/</a>
  </p>
</div>