]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/pprof/pprof.go
runtime: add available godoc link
[gostls13.git] / src / runtime / pprof / pprof.go
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.
4
5 // Package pprof writes runtime profiling data in the format expected
6 // by the pprof visualization tool.
7 //
8 // # Profiling a Go program
9 //
10 // The first step to profiling a Go program is to enable profiling.
11 // Support for profiling benchmarks built with the standard testing
12 // package is built into go test. For example, the following command
13 // runs benchmarks in the current directory and writes the CPU and
14 // memory profiles to cpu.prof and mem.prof:
15 //
16 //      go test -cpuprofile cpu.prof -memprofile mem.prof -bench .
17 //
18 // To add equivalent profiling support to a standalone program, add
19 // code like the following to your main function:
20 //
21 //      var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
22 //      var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
23 //
24 //      func main() {
25 //          flag.Parse()
26 //          if *cpuprofile != "" {
27 //              f, err := os.Create(*cpuprofile)
28 //              if err != nil {
29 //                  log.Fatal("could not create CPU profile: ", err)
30 //              }
31 //              defer f.Close() // error handling omitted for example
32 //              if err := pprof.StartCPUProfile(f); err != nil {
33 //                  log.Fatal("could not start CPU profile: ", err)
34 //              }
35 //              defer pprof.StopCPUProfile()
36 //          }
37 //
38 //          // ... rest of the program ...
39 //
40 //          if *memprofile != "" {
41 //              f, err := os.Create(*memprofile)
42 //              if err != nil {
43 //                  log.Fatal("could not create memory profile: ", err)
44 //              }
45 //              defer f.Close() // error handling omitted for example
46 //              runtime.GC() // get up-to-date statistics
47 //              if err := pprof.WriteHeapProfile(f); err != nil {
48 //                  log.Fatal("could not write memory profile: ", err)
49 //              }
50 //          }
51 //      }
52 //
53 // There is also a standard HTTP interface to profiling data. Adding
54 // the following line will install handlers under the /debug/pprof/
55 // URL to download live profiles:
56 //
57 //      import _ "net/http/pprof"
58 //
59 // See the net/http/pprof package for more details.
60 //
61 // Profiles can then be visualized with the pprof tool:
62 //
63 //      go tool pprof cpu.prof
64 //
65 // There are many commands available from the pprof command line.
66 // Commonly used commands include "top", which prints a summary of the
67 // top program hot-spots, and "web", which opens an interactive graph
68 // of hot-spots and their call graphs. Use "help" for information on
69 // all pprof commands.
70 //
71 // For more information about pprof, see
72 // https://github.com/google/pprof/blob/master/doc/README.md.
73 package pprof
74
75 import (
76         "bufio"
77         "fmt"
78         "internal/abi"
79         "io"
80         "runtime"
81         "sort"
82         "strings"
83         "sync"
84         "text/tabwriter"
85         "time"
86         "unsafe"
87 )
88
89 // BUG(rsc): Profiles are only as good as the kernel support used to generate them.
90 // See https://golang.org/issue/13841 for details about known problems.
91
92 // A Profile is a collection of stack traces showing the call sequences
93 // that led to instances of a particular event, such as allocation.
94 // Packages can create and maintain their own profiles; the most common
95 // use is for tracking resources that must be explicitly closed, such as files
96 // or network connections.
97 //
98 // A Profile's methods can be called from multiple goroutines simultaneously.
99 //
100 // Each Profile has a unique name. A few profiles are predefined:
101 //
102 //      goroutine    - stack traces of all current goroutines
103 //      heap         - a sampling of memory allocations of live objects
104 //      allocs       - a sampling of all past memory allocations
105 //      threadcreate - stack traces that led to the creation of new OS threads
106 //      block        - stack traces that led to blocking on synchronization primitives
107 //      mutex        - stack traces of holders of contended mutexes
108 //
109 // These predefined profiles maintain themselves and panic on an explicit
110 // [Profile.Add] or [Profile.Remove] method call.
111 //
112 // The heap profile reports statistics as of the most recently completed
113 // garbage collection; it elides more recent allocation to avoid skewing
114 // the profile away from live data and toward garbage.
115 // If there has been no garbage collection at all, the heap profile reports
116 // all known allocations. This exception helps mainly in programs running
117 // without garbage collection enabled, usually for debugging purposes.
118 //
119 // The heap profile tracks both the allocation sites for all live objects in
120 // the application memory and for all objects allocated since the program start.
121 // Pprof's -inuse_space, -inuse_objects, -alloc_space, and -alloc_objects
122 // flags select which to display, defaulting to -inuse_space (live objects,
123 // scaled by size).
124 //
125 // The allocs profile is the same as the heap profile but changes the default
126 // pprof display to -alloc_space, the total number of bytes allocated since
127 // the program began (including garbage-collected bytes).
128 //
129 // The CPU profile is not available as a Profile. It has a special API,
130 // the [StartCPUProfile] and [StopCPUProfile] functions, because it streams
131 // output to a writer during profiling.
132 type Profile struct {
133         name  string
134         mu    sync.Mutex
135         m     map[any][]uintptr
136         count func() int
137         write func(io.Writer, int) error
138 }
139
140 // profiles records all registered profiles.
141 var profiles struct {
142         mu sync.Mutex
143         m  map[string]*Profile
144 }
145
146 var goroutineProfile = &Profile{
147         name:  "goroutine",
148         count: countGoroutine,
149         write: writeGoroutine,
150 }
151
152 var threadcreateProfile = &Profile{
153         name:  "threadcreate",
154         count: countThreadCreate,
155         write: writeThreadCreate,
156 }
157
158 var heapProfile = &Profile{
159         name:  "heap",
160         count: countHeap,
161         write: writeHeap,
162 }
163
164 var allocsProfile = &Profile{
165         name:  "allocs",
166         count: countHeap, // identical to heap profile
167         write: writeAlloc,
168 }
169
170 var blockProfile = &Profile{
171         name:  "block",
172         count: countBlock,
173         write: writeBlock,
174 }
175
176 var mutexProfile = &Profile{
177         name:  "mutex",
178         count: countMutex,
179         write: writeMutex,
180 }
181
182 func lockProfiles() {
183         profiles.mu.Lock()
184         if profiles.m == nil {
185                 // Initial built-in profiles.
186                 profiles.m = map[string]*Profile{
187                         "goroutine":    goroutineProfile,
188                         "threadcreate": threadcreateProfile,
189                         "heap":         heapProfile,
190                         "allocs":       allocsProfile,
191                         "block":        blockProfile,
192                         "mutex":        mutexProfile,
193                 }
194         }
195 }
196
197 func unlockProfiles() {
198         profiles.mu.Unlock()
199 }
200
201 // NewProfile creates a new profile with the given name.
202 // If a profile with that name already exists, NewProfile panics.
203 // The convention is to use a 'import/path.' prefix to create
204 // separate name spaces for each package.
205 // For compatibility with various tools that read pprof data,
206 // profile names should not contain spaces.
207 func NewProfile(name string) *Profile {
208         lockProfiles()
209         defer unlockProfiles()
210         if name == "" {
211                 panic("pprof: NewProfile with empty name")
212         }
213         if profiles.m[name] != nil {
214                 panic("pprof: NewProfile name already in use: " + name)
215         }
216         p := &Profile{
217                 name: name,
218                 m:    map[any][]uintptr{},
219         }
220         profiles.m[name] = p
221         return p
222 }
223
224 // Lookup returns the profile with the given name, or nil if no such profile exists.
225 func Lookup(name string) *Profile {
226         lockProfiles()
227         defer unlockProfiles()
228         return profiles.m[name]
229 }
230
231 // Profiles returns a slice of all the known profiles, sorted by name.
232 func Profiles() []*Profile {
233         lockProfiles()
234         defer unlockProfiles()
235
236         all := make([]*Profile, 0, len(profiles.m))
237         for _, p := range profiles.m {
238                 all = append(all, p)
239         }
240
241         sort.Slice(all, func(i, j int) bool { return all[i].name < all[j].name })
242         return all
243 }
244
245 // Name returns this profile's name, which can be passed to [Lookup] to reobtain the profile.
246 func (p *Profile) Name() string {
247         return p.name
248 }
249
250 // Count returns the number of execution stacks currently in the profile.
251 func (p *Profile) Count() int {
252         p.mu.Lock()
253         defer p.mu.Unlock()
254         if p.count != nil {
255                 return p.count()
256         }
257         return len(p.m)
258 }
259
260 // Add adds the current execution stack to the profile, associated with value.
261 // Add stores value in an internal map, so value must be suitable for use as
262 // a map key and will not be garbage collected until the corresponding
263 // call to [Profile.Remove]. Add panics if the profile already contains a stack for value.
264 //
265 // The skip parameter has the same meaning as [runtime.Caller]'s skip
266 // and controls where the stack trace begins. Passing skip=0 begins the
267 // trace in the function calling Add. For example, given this
268 // execution stack:
269 //
270 //      Add
271 //      called from rpc.NewClient
272 //      called from mypkg.Run
273 //      called from main.main
274 //
275 // Passing skip=0 begins the stack trace at the call to Add inside rpc.NewClient.
276 // Passing skip=1 begins the stack trace at the call to NewClient inside mypkg.Run.
277 func (p *Profile) Add(value any, skip int) {
278         if p.name == "" {
279                 panic("pprof: use of uninitialized Profile")
280         }
281         if p.write != nil {
282                 panic("pprof: Add called on built-in Profile " + p.name)
283         }
284
285         stk := make([]uintptr, 32)
286         n := runtime.Callers(skip+1, stk[:])
287         stk = stk[:n]
288         if len(stk) == 0 {
289                 // The value for skip is too large, and there's no stack trace to record.
290                 stk = []uintptr{abi.FuncPCABIInternal(lostProfileEvent)}
291         }
292
293         p.mu.Lock()
294         defer p.mu.Unlock()
295         if p.m[value] != nil {
296                 panic("pprof: Profile.Add of duplicate value")
297         }
298         p.m[value] = stk
299 }
300
301 // Remove removes the execution stack associated with value from the profile.
302 // It is a no-op if the value is not in the profile.
303 func (p *Profile) Remove(value any) {
304         p.mu.Lock()
305         defer p.mu.Unlock()
306         delete(p.m, value)
307 }
308
309 // WriteTo writes a pprof-formatted snapshot of the profile to w.
310 // If a write to w returns an error, WriteTo returns that error.
311 // Otherwise, WriteTo returns nil.
312 //
313 // The debug parameter enables additional output.
314 // Passing debug=0 writes the gzip-compressed protocol buffer described
315 // in https://github.com/google/pprof/tree/master/proto#overview.
316 // Passing debug=1 writes the legacy text format with comments
317 // translating addresses to function names and line numbers, so that a
318 // programmer can read the profile without tools.
319 //
320 // The predefined profiles may assign meaning to other debug values;
321 // for example, when printing the "goroutine" profile, debug=2 means to
322 // print the goroutine stacks in the same form that a Go program uses
323 // when dying due to an unrecovered panic.
324 func (p *Profile) WriteTo(w io.Writer, debug int) error {
325         if p.name == "" {
326                 panic("pprof: use of zero Profile")
327         }
328         if p.write != nil {
329                 return p.write(w, debug)
330         }
331
332         // Obtain consistent snapshot under lock; then process without lock.
333         p.mu.Lock()
334         all := make([][]uintptr, 0, len(p.m))
335         for _, stk := range p.m {
336                 all = append(all, stk)
337         }
338         p.mu.Unlock()
339
340         // Map order is non-deterministic; make output deterministic.
341         sort.Slice(all, func(i, j int) bool {
342                 t, u := all[i], all[j]
343                 for k := 0; k < len(t) && k < len(u); k++ {
344                         if t[k] != u[k] {
345                                 return t[k] < u[k]
346                         }
347                 }
348                 return len(t) < len(u)
349         })
350
351         return printCountProfile(w, debug, p.name, stackProfile(all))
352 }
353
354 type stackProfile [][]uintptr
355
356 func (x stackProfile) Len() int              { return len(x) }
357 func (x stackProfile) Stack(i int) []uintptr { return x[i] }
358 func (x stackProfile) Label(i int) *labelMap { return nil }
359
360 // A countProfile is a set of stack traces to be printed as counts
361 // grouped by stack trace. There are multiple implementations:
362 // all that matters is that we can find out how many traces there are
363 // and obtain each trace in turn.
364 type countProfile interface {
365         Len() int
366         Stack(i int) []uintptr
367         Label(i int) *labelMap
368 }
369
370 // printCountCycleProfile outputs block profile records (for block or mutex profiles)
371 // as the pprof-proto format output. Translations from cycle count to time duration
372 // are done because The proto expects count and time (nanoseconds) instead of count
373 // and the number of cycles for block, contention profiles.
374 func printCountCycleProfile(w io.Writer, countName, cycleName string, records []runtime.BlockProfileRecord) error {
375         // Output profile in protobuf form.
376         b := newProfileBuilder(w)
377         b.pbValueType(tagProfile_PeriodType, countName, "count")
378         b.pb.int64Opt(tagProfile_Period, 1)
379         b.pbValueType(tagProfile_SampleType, countName, "count")
380         b.pbValueType(tagProfile_SampleType, cycleName, "nanoseconds")
381
382         cpuGHz := float64(runtime_cyclesPerSecond()) / 1e9
383
384         values := []int64{0, 0}
385         var locs []uint64
386         for _, r := range records {
387                 values[0] = r.Count
388                 values[1] = int64(float64(r.Cycles) / cpuGHz)
389                 // For count profiles, all stack addresses are
390                 // return PCs, which is what appendLocsForStack expects.
391                 locs = b.appendLocsForStack(locs[:0], r.Stack())
392                 b.pbSample(values, locs, nil)
393         }
394         b.build()
395         return nil
396 }
397
398 // printCountProfile prints a countProfile at the specified debug level.
399 // The profile will be in compressed proto format unless debug is nonzero.
400 func printCountProfile(w io.Writer, debug int, name string, p countProfile) error {
401         // Build count of each stack.
402         var buf strings.Builder
403         key := func(stk []uintptr, lbls *labelMap) string {
404                 buf.Reset()
405                 fmt.Fprintf(&buf, "@")
406                 for _, pc := range stk {
407                         fmt.Fprintf(&buf, " %#x", pc)
408                 }
409                 if lbls != nil {
410                         buf.WriteString("\n# labels: ")
411                         buf.WriteString(lbls.String())
412                 }
413                 return buf.String()
414         }
415         count := map[string]int{}
416         index := map[string]int{}
417         var keys []string
418         n := p.Len()
419         for i := 0; i < n; i++ {
420                 k := key(p.Stack(i), p.Label(i))
421                 if count[k] == 0 {
422                         index[k] = i
423                         keys = append(keys, k)
424                 }
425                 count[k]++
426         }
427
428         sort.Sort(&keysByCount{keys, count})
429
430         if debug > 0 {
431                 // Print debug profile in legacy format
432                 tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
433                 fmt.Fprintf(tw, "%s profile: total %d\n", name, p.Len())
434                 for _, k := range keys {
435                         fmt.Fprintf(tw, "%d %s\n", count[k], k)
436                         printStackRecord(tw, p.Stack(index[k]), false)
437                 }
438                 return tw.Flush()
439         }
440
441         // Output profile in protobuf form.
442         b := newProfileBuilder(w)
443         b.pbValueType(tagProfile_PeriodType, name, "count")
444         b.pb.int64Opt(tagProfile_Period, 1)
445         b.pbValueType(tagProfile_SampleType, name, "count")
446
447         values := []int64{0}
448         var locs []uint64
449         for _, k := range keys {
450                 values[0] = int64(count[k])
451                 // For count profiles, all stack addresses are
452                 // return PCs, which is what appendLocsForStack expects.
453                 locs = b.appendLocsForStack(locs[:0], p.Stack(index[k]))
454                 idx := index[k]
455                 var labels func()
456                 if p.Label(idx) != nil {
457                         labels = func() {
458                                 for k, v := range *p.Label(idx) {
459                                         b.pbLabel(tagSample_Label, k, v, 0)
460                                 }
461                         }
462                 }
463                 b.pbSample(values, locs, labels)
464         }
465         b.build()
466         return nil
467 }
468
469 // keysByCount sorts keys with higher counts first, breaking ties by key string order.
470 type keysByCount struct {
471         keys  []string
472         count map[string]int
473 }
474
475 func (x *keysByCount) Len() int      { return len(x.keys) }
476 func (x *keysByCount) Swap(i, j int) { x.keys[i], x.keys[j] = x.keys[j], x.keys[i] }
477 func (x *keysByCount) Less(i, j int) bool {
478         ki, kj := x.keys[i], x.keys[j]
479         ci, cj := x.count[ki], x.count[kj]
480         if ci != cj {
481                 return ci > cj
482         }
483         return ki < kj
484 }
485
486 // printStackRecord prints the function + source line information
487 // for a single stack trace.
488 func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
489         show := allFrames
490         frames := runtime.CallersFrames(stk)
491         for {
492                 frame, more := frames.Next()
493                 name := frame.Function
494                 if name == "" {
495                         show = true
496                         fmt.Fprintf(w, "#\t%#x\n", frame.PC)
497                 } else if name != "runtime.goexit" && (show || !strings.HasPrefix(name, "runtime.")) {
498                         // Hide runtime.goexit and any runtime functions at the beginning.
499                         // This is useful mainly for allocation traces.
500                         show = true
501                         fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", frame.PC, name, frame.PC-frame.Entry, frame.File, frame.Line)
502                 }
503                 if !more {
504                         break
505                 }
506         }
507         if !show {
508                 // We didn't print anything; do it again,
509                 // and this time include runtime functions.
510                 printStackRecord(w, stk, true)
511                 return
512         }
513         fmt.Fprintf(w, "\n")
514 }
515
516 // Interface to system profiles.
517
518 // WriteHeapProfile is shorthand for [Lookup]("heap").WriteTo(w, 0).
519 // It is preserved for backwards compatibility.
520 func WriteHeapProfile(w io.Writer) error {
521         return writeHeap(w, 0)
522 }
523
524 // countHeap returns the number of records in the heap profile.
525 func countHeap() int {
526         n, _ := runtime.MemProfile(nil, true)
527         return n
528 }
529
530 // writeHeap writes the current runtime heap profile to w.
531 func writeHeap(w io.Writer, debug int) error {
532         return writeHeapInternal(w, debug, "")
533 }
534
535 // writeAlloc writes the current runtime heap profile to w
536 // with the total allocation space as the default sample type.
537 func writeAlloc(w io.Writer, debug int) error {
538         return writeHeapInternal(w, debug, "alloc_space")
539 }
540
541 func writeHeapInternal(w io.Writer, debug int, defaultSampleType string) error {
542         var memStats *runtime.MemStats
543         if debug != 0 {
544                 // Read mem stats first, so that our other allocations
545                 // do not appear in the statistics.
546                 memStats = new(runtime.MemStats)
547                 runtime.ReadMemStats(memStats)
548         }
549
550         // Find out how many records there are (MemProfile(nil, true)),
551         // allocate that many records, and get the data.
552         // There's a race—more records might be added between
553         // the two calls—so allocate a few extra records for safety
554         // and also try again if we're very unlucky.
555         // The loop should only execute one iteration in the common case.
556         var p []runtime.MemProfileRecord
557         n, ok := runtime.MemProfile(nil, true)
558         for {
559                 // Allocate room for a slightly bigger profile,
560                 // in case a few more entries have been added
561                 // since the call to MemProfile.
562                 p = make([]runtime.MemProfileRecord, n+50)
563                 n, ok = runtime.MemProfile(p, true)
564                 if ok {
565                         p = p[0:n]
566                         break
567                 }
568                 // Profile grew; try again.
569         }
570
571         if debug == 0 {
572                 return writeHeapProto(w, p, int64(runtime.MemProfileRate), defaultSampleType)
573         }
574
575         sort.Slice(p, func(i, j int) bool { return p[i].InUseBytes() > p[j].InUseBytes() })
576
577         b := bufio.NewWriter(w)
578         tw := tabwriter.NewWriter(b, 1, 8, 1, '\t', 0)
579         w = tw
580
581         var total runtime.MemProfileRecord
582         for i := range p {
583                 r := &p[i]
584                 total.AllocBytes += r.AllocBytes
585                 total.AllocObjects += r.AllocObjects
586                 total.FreeBytes += r.FreeBytes
587                 total.FreeObjects += r.FreeObjects
588         }
589
590         // Technically the rate is MemProfileRate not 2*MemProfileRate,
591         // but early versions of the C++ heap profiler reported 2*MemProfileRate,
592         // so that's what pprof has come to expect.
593         rate := 2 * runtime.MemProfileRate
594
595         // pprof reads a profile with alloc == inuse as being a "2-column" profile
596         // (objects and bytes, not distinguishing alloc from inuse),
597         // but then such a profile can't be merged using pprof *.prof with
598         // other 4-column profiles where alloc != inuse.
599         // The easiest way to avoid this bug is to adjust allocBytes so it's never == inuseBytes.
600         // pprof doesn't use these header values anymore except for checking equality.
601         inUseBytes := total.InUseBytes()
602         allocBytes := total.AllocBytes
603         if inUseBytes == allocBytes {
604                 allocBytes++
605         }
606
607         fmt.Fprintf(w, "heap profile: %d: %d [%d: %d] @ heap/%d\n",
608                 total.InUseObjects(), inUseBytes,
609                 total.AllocObjects, allocBytes,
610                 rate)
611
612         for i := range p {
613                 r := &p[i]
614                 fmt.Fprintf(w, "%d: %d [%d: %d] @",
615                         r.InUseObjects(), r.InUseBytes(),
616                         r.AllocObjects, r.AllocBytes)
617                 for _, pc := range r.Stack() {
618                         fmt.Fprintf(w, " %#x", pc)
619                 }
620                 fmt.Fprintf(w, "\n")
621                 printStackRecord(w, r.Stack(), false)
622         }
623
624         // Print memstats information too.
625         // Pprof will ignore, but useful for people
626         s := memStats
627         fmt.Fprintf(w, "\n# runtime.MemStats\n")
628         fmt.Fprintf(w, "# Alloc = %d\n", s.Alloc)
629         fmt.Fprintf(w, "# TotalAlloc = %d\n", s.TotalAlloc)
630         fmt.Fprintf(w, "# Sys = %d\n", s.Sys)
631         fmt.Fprintf(w, "# Lookups = %d\n", s.Lookups)
632         fmt.Fprintf(w, "# Mallocs = %d\n", s.Mallocs)
633         fmt.Fprintf(w, "# Frees = %d\n", s.Frees)
634
635         fmt.Fprintf(w, "# HeapAlloc = %d\n", s.HeapAlloc)
636         fmt.Fprintf(w, "# HeapSys = %d\n", s.HeapSys)
637         fmt.Fprintf(w, "# HeapIdle = %d\n", s.HeapIdle)
638         fmt.Fprintf(w, "# HeapInuse = %d\n", s.HeapInuse)
639         fmt.Fprintf(w, "# HeapReleased = %d\n", s.HeapReleased)
640         fmt.Fprintf(w, "# HeapObjects = %d\n", s.HeapObjects)
641
642         fmt.Fprintf(w, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
643         fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
644         fmt.Fprintf(w, "# MCache = %d / %d\n", s.MCacheInuse, s.MCacheSys)
645         fmt.Fprintf(w, "# BuckHashSys = %d\n", s.BuckHashSys)
646         fmt.Fprintf(w, "# GCSys = %d\n", s.GCSys)
647         fmt.Fprintf(w, "# OtherSys = %d\n", s.OtherSys)
648
649         fmt.Fprintf(w, "# NextGC = %d\n", s.NextGC)
650         fmt.Fprintf(w, "# LastGC = %d\n", s.LastGC)
651         fmt.Fprintf(w, "# PauseNs = %d\n", s.PauseNs)
652         fmt.Fprintf(w, "# PauseEnd = %d\n", s.PauseEnd)
653         fmt.Fprintf(w, "# NumGC = %d\n", s.NumGC)
654         fmt.Fprintf(w, "# NumForcedGC = %d\n", s.NumForcedGC)
655         fmt.Fprintf(w, "# GCCPUFraction = %v\n", s.GCCPUFraction)
656         fmt.Fprintf(w, "# DebugGC = %v\n", s.DebugGC)
657
658         // Also flush out MaxRSS on supported platforms.
659         addMaxRSS(w)
660
661         tw.Flush()
662         return b.Flush()
663 }
664
665 // countThreadCreate returns the size of the current ThreadCreateProfile.
666 func countThreadCreate() int {
667         n, _ := runtime.ThreadCreateProfile(nil)
668         return n
669 }
670
671 // writeThreadCreate writes the current runtime ThreadCreateProfile to w.
672 func writeThreadCreate(w io.Writer, debug int) error {
673         // Until https://golang.org/issues/6104 is addressed, wrap
674         // ThreadCreateProfile because there's no point in tracking labels when we
675         // don't get any stack-traces.
676         return writeRuntimeProfile(w, debug, "threadcreate", func(p []runtime.StackRecord, _ []unsafe.Pointer) (n int, ok bool) {
677                 return runtime.ThreadCreateProfile(p)
678         })
679 }
680
681 // countGoroutine returns the number of goroutines.
682 func countGoroutine() int {
683         return runtime.NumGoroutine()
684 }
685
686 // runtime_goroutineProfileWithLabels is defined in runtime/mprof.go
687 func runtime_goroutineProfileWithLabels(p []runtime.StackRecord, labels []unsafe.Pointer) (n int, ok bool)
688
689 // writeGoroutine writes the current runtime GoroutineProfile to w.
690 func writeGoroutine(w io.Writer, debug int) error {
691         if debug >= 2 {
692                 return writeGoroutineStacks(w)
693         }
694         return writeRuntimeProfile(w, debug, "goroutine", runtime_goroutineProfileWithLabels)
695 }
696
697 func writeGoroutineStacks(w io.Writer) error {
698         // We don't know how big the buffer needs to be to collect
699         // all the goroutines. Start with 1 MB and try a few times, doubling each time.
700         // Give up and use a truncated trace if 64 MB is not enough.
701         buf := make([]byte, 1<<20)
702         for i := 0; ; i++ {
703                 n := runtime.Stack(buf, true)
704                 if n < len(buf) {
705                         buf = buf[:n]
706                         break
707                 }
708                 if len(buf) >= 64<<20 {
709                         // Filled 64 MB - stop there.
710                         break
711                 }
712                 buf = make([]byte, 2*len(buf))
713         }
714         _, err := w.Write(buf)
715         return err
716 }
717
718 func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runtime.StackRecord, []unsafe.Pointer) (int, bool)) error {
719         // Find out how many records there are (fetch(nil)),
720         // allocate that many records, and get the data.
721         // There's a race—more records might be added between
722         // the two calls—so allocate a few extra records for safety
723         // and also try again if we're very unlucky.
724         // The loop should only execute one iteration in the common case.
725         var p []runtime.StackRecord
726         var labels []unsafe.Pointer
727         n, ok := fetch(nil, nil)
728         for {
729                 // Allocate room for a slightly bigger profile,
730                 // in case a few more entries have been added
731                 // since the call to ThreadProfile.
732                 p = make([]runtime.StackRecord, n+10)
733                 labels = make([]unsafe.Pointer, n+10)
734                 n, ok = fetch(p, labels)
735                 if ok {
736                         p = p[0:n]
737                         break
738                 }
739                 // Profile grew; try again.
740         }
741
742         return printCountProfile(w, debug, name, &runtimeProfile{p, labels})
743 }
744
745 type runtimeProfile struct {
746         stk    []runtime.StackRecord
747         labels []unsafe.Pointer
748 }
749
750 func (p *runtimeProfile) Len() int              { return len(p.stk) }
751 func (p *runtimeProfile) Stack(i int) []uintptr { return p.stk[i].Stack() }
752 func (p *runtimeProfile) Label(i int) *labelMap { return (*labelMap)(p.labels[i]) }
753
754 var cpu struct {
755         sync.Mutex
756         profiling bool
757         done      chan bool
758 }
759
760 // StartCPUProfile enables CPU profiling for the current process.
761 // While profiling, the profile will be buffered and written to w.
762 // StartCPUProfile returns an error if profiling is already enabled.
763 //
764 // On Unix-like systems, StartCPUProfile does not work by default for
765 // Go code built with -buildmode=c-archive or -buildmode=c-shared.
766 // StartCPUProfile relies on the SIGPROF signal, but that signal will
767 // be delivered to the main program's SIGPROF signal handler (if any)
768 // not to the one used by Go. To make it work, call [os/signal.Notify]
769 // for [syscall.SIGPROF], but note that doing so may break any profiling
770 // being done by the main program.
771 func StartCPUProfile(w io.Writer) error {
772         // The runtime routines allow a variable profiling rate,
773         // but in practice operating systems cannot trigger signals
774         // at more than about 500 Hz, and our processing of the
775         // signal is not cheap (mostly getting the stack trace).
776         // 100 Hz is a reasonable choice: it is frequent enough to
777         // produce useful data, rare enough not to bog down the
778         // system, and a nice round number to make it easy to
779         // convert sample counts to seconds. Instead of requiring
780         // each client to specify the frequency, we hard code it.
781         const hz = 100
782
783         cpu.Lock()
784         defer cpu.Unlock()
785         if cpu.done == nil {
786                 cpu.done = make(chan bool)
787         }
788         // Double-check.
789         if cpu.profiling {
790                 return fmt.Errorf("cpu profiling already in use")
791         }
792         cpu.profiling = true
793         runtime.SetCPUProfileRate(hz)
794         go profileWriter(w)
795         return nil
796 }
797
798 // readProfile, provided by the runtime, returns the next chunk of
799 // binary CPU profiling stack trace data, blocking until data is available.
800 // If profiling is turned off and all the profile data accumulated while it was
801 // on has been returned, readProfile returns eof=true.
802 // The caller must save the returned data and tags before calling readProfile again.
803 func readProfile() (data []uint64, tags []unsafe.Pointer, eof bool)
804
805 func profileWriter(w io.Writer) {
806         b := newProfileBuilder(w)
807         var err error
808         for {
809                 time.Sleep(100 * time.Millisecond)
810                 data, tags, eof := readProfile()
811                 if e := b.addCPUData(data, tags); e != nil && err == nil {
812                         err = e
813                 }
814                 if eof {
815                         break
816                 }
817         }
818         if err != nil {
819                 // The runtime should never produce an invalid or truncated profile.
820                 // It drops records that can't fit into its log buffers.
821                 panic("runtime/pprof: converting profile: " + err.Error())
822         }
823         b.build()
824         cpu.done <- true
825 }
826
827 // StopCPUProfile stops the current CPU profile, if any.
828 // StopCPUProfile only returns after all the writes for the
829 // profile have completed.
830 func StopCPUProfile() {
831         cpu.Lock()
832         defer cpu.Unlock()
833
834         if !cpu.profiling {
835                 return
836         }
837         cpu.profiling = false
838         runtime.SetCPUProfileRate(0)
839         <-cpu.done
840 }
841
842 // countBlock returns the number of records in the blocking profile.
843 func countBlock() int {
844         n, _ := runtime.BlockProfile(nil)
845         return n
846 }
847
848 // countMutex returns the number of records in the mutex profile.
849 func countMutex() int {
850         n, _ := runtime.MutexProfile(nil)
851         return n
852 }
853
854 // writeBlock writes the current blocking profile to w.
855 func writeBlock(w io.Writer, debug int) error {
856         return writeProfileInternal(w, debug, "contention", runtime.BlockProfile)
857 }
858
859 // writeMutex writes the current mutex profile to w.
860 func writeMutex(w io.Writer, debug int) error {
861         return writeProfileInternal(w, debug, "mutex", runtime.MutexProfile)
862 }
863
864 // writeProfileInternal writes the current blocking or mutex profile depending on the passed parameters.
865 func writeProfileInternal(w io.Writer, debug int, name string, runtimeProfile func([]runtime.BlockProfileRecord) (int, bool)) error {
866         var p []runtime.BlockProfileRecord
867         n, ok := runtimeProfile(nil)
868         for {
869                 p = make([]runtime.BlockProfileRecord, n+50)
870                 n, ok = runtimeProfile(p)
871                 if ok {
872                         p = p[:n]
873                         break
874                 }
875         }
876
877         sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
878
879         if debug <= 0 {
880                 return printCountCycleProfile(w, "contentions", "delay", p)
881         }
882
883         b := bufio.NewWriter(w)
884         tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
885         w = tw
886
887         fmt.Fprintf(w, "--- %v:\n", name)
888         fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
889         if name == "mutex" {
890                 fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1))
891         }
892         for i := range p {
893                 r := &p[i]
894                 fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
895                 for _, pc := range r.Stack() {
896                         fmt.Fprintf(w, " %#x", pc)
897                 }
898                 fmt.Fprint(w, "\n")
899                 if debug > 0 {
900                         printStackRecord(w, r.Stack(), true)
901                 }
902         }
903
904         if tw != nil {
905                 tw.Flush()
906         }
907         return b.Flush()
908 }
909
910 func runtime_cyclesPerSecond() int64