...

Source file 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()
    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()
    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		"bytes"
    78		"fmt"
    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	// Add or 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	//
   133	type Profile struct {
   134		name  string
   135		mu    sync.Mutex
   136		m     map[interface{}][]uintptr
   137		count func() int
   138		write func(io.Writer, int) error
   139	}
   140	
   141	// profiles records all registered profiles.
   142	var profiles struct {
   143		mu sync.Mutex
   144		m  map[string]*Profile
   145	}
   146	
   147	var goroutineProfile = &Profile{
   148		name:  "goroutine",
   149		count: countGoroutine,
   150		write: writeGoroutine,
   151	}
   152	
   153	var threadcreateProfile = &Profile{
   154		name:  "threadcreate",
   155		count: countThreadCreate,
   156		write: writeThreadCreate,
   157	}
   158	
   159	var heapProfile = &Profile{
   160		name:  "heap",
   161		count: countHeap,
   162		write: writeHeap,
   163	}
   164	
   165	var allocsProfile = &Profile{
   166		name:  "allocs",
   167		count: countHeap, // identical to heap profile
   168		write: writeAlloc,
   169	}
   170	
   171	var blockProfile = &Profile{
   172		name:  "block",
   173		count: countBlock,
   174		write: writeBlock,
   175	}
   176	
   177	var mutexProfile = &Profile{
   178		name:  "mutex",
   179		count: countMutex,
   180		write: writeMutex,
   181	}
   182	
   183	func lockProfiles() {
   184		profiles.mu.Lock()
   185		if profiles.m == nil {
   186			// Initial built-in profiles.
   187			profiles.m = map[string]*Profile{
   188				"goroutine":    goroutineProfile,
   189				"threadcreate": threadcreateProfile,
   190				"heap":         heapProfile,
   191				"allocs":       allocsProfile,
   192				"block":        blockProfile,
   193				"mutex":        mutexProfile,
   194			}
   195		}
   196	}
   197	
   198	func unlockProfiles() {
   199		profiles.mu.Unlock()
   200	}
   201	
   202	// NewProfile creates a new profile with the given name.
   203	// If a profile with that name already exists, NewProfile panics.
   204	// The convention is to use a 'import/path.' prefix to create
   205	// separate name spaces for each package.
   206	// For compatibility with various tools that read pprof data,
   207	// profile names should not contain spaces.
   208	func NewProfile(name string) *Profile {
   209		lockProfiles()
   210		defer unlockProfiles()
   211		if name == "" {
   212			panic("pprof: NewProfile with empty name")
   213		}
   214		if profiles.m[name] != nil {
   215			panic("pprof: NewProfile name already in use: " + name)
   216		}
   217		p := &Profile{
   218			name: name,
   219			m:    map[interface{}][]uintptr{},
   220		}
   221		profiles.m[name] = p
   222		return p
   223	}
   224	
   225	// Lookup returns the profile with the given name, or nil if no such profile exists.
   226	func Lookup(name string) *Profile {
   227		lockProfiles()
   228		defer unlockProfiles()
   229		return profiles.m[name]
   230	}
   231	
   232	// Profiles returns a slice of all the known profiles, sorted by name.
   233	func Profiles() []*Profile {
   234		lockProfiles()
   235		defer unlockProfiles()
   236	
   237		all := make([]*Profile, 0, len(profiles.m))
   238		for _, p := range profiles.m {
   239			all = append(all, p)
   240		}
   241	
   242		sort.Slice(all, func(i, j int) bool { return all[i].name < all[j].name })
   243		return all
   244	}
   245	
   246	// Name returns this profile's name, which can be passed to Lookup to reobtain the profile.
   247	func (p *Profile) Name() string {
   248		return p.name
   249	}
   250	
   251	// Count returns the number of execution stacks currently in the profile.
   252	func (p *Profile) Count() int {
   253		p.mu.Lock()
   254		defer p.mu.Unlock()
   255		if p.count != nil {
   256			return p.count()
   257		}
   258		return len(p.m)
   259	}
   260	
   261	// Add adds the current execution stack to the profile, associated with value.
   262	// Add stores value in an internal map, so value must be suitable for use as
   263	// a map key and will not be garbage collected until the corresponding
   264	// call to Remove. Add panics if the profile already contains a stack for value.
   265	//
   266	// The skip parameter has the same meaning as runtime.Caller's skip
   267	// and controls where the stack trace begins. Passing skip=0 begins the
   268	// trace in the function calling Add. For example, given this
   269	// execution stack:
   270	//
   271	//	Add
   272	//	called from rpc.NewClient
   273	//	called from mypkg.Run
   274	//	called from main.main
   275	//
   276	// Passing skip=0 begins the stack trace at the call to Add inside rpc.NewClient.
   277	// Passing skip=1 begins the stack trace at the call to NewClient inside mypkg.Run.
   278	//
   279	func (p *Profile) Add(value interface{}, skip int) {
   280		if p.name == "" {
   281			panic("pprof: use of uninitialized Profile")
   282		}
   283		if p.write != nil {
   284			panic("pprof: Add called on built-in Profile " + p.name)
   285		}
   286	
   287		stk := make([]uintptr, 32)
   288		n := runtime.Callers(skip+1, stk[:])
   289		stk = stk[:n]
   290		if len(stk) == 0 {
   291			// The value for skip is too large, and there's no stack trace to record.
   292			stk = []uintptr{funcPC(lostProfileEvent)}
   293		}
   294	
   295		p.mu.Lock()
   296		defer p.mu.Unlock()
   297		if p.m[value] != nil {
   298			panic("pprof: Profile.Add of duplicate value")
   299		}
   300		p.m[value] = stk
   301	}
   302	
   303	// Remove removes the execution stack associated with value from the profile.
   304	// It is a no-op if the value is not in the profile.
   305	func (p *Profile) Remove(value interface{}) {
   306		p.mu.Lock()
   307		defer p.mu.Unlock()
   308		delete(p.m, value)
   309	}
   310	
   311	// WriteTo writes a pprof-formatted snapshot of the profile to w.
   312	// If a write to w returns an error, WriteTo returns that error.
   313	// Otherwise, WriteTo returns nil.
   314	//
   315	// The debug parameter enables additional output.
   316	// Passing debug=0 prints only the hexadecimal addresses that pprof needs.
   317	// Passing debug=1 adds comments translating addresses to function names
   318	// and line numbers, so that a 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	
   359	// A countProfile is a set of stack traces to be printed as counts
   360	// grouped by stack trace. There are multiple implementations:
   361	// all that matters is that we can find out how many traces there are
   362	// and obtain each trace in turn.
   363	type countProfile interface {
   364		Len() int
   365		Stack(i int) []uintptr
   366	}
   367	
   368	// printCountCycleProfile outputs block profile records (for block or mutex profiles)
   369	// as the pprof-proto format output. Translations from cycle count to time duration
   370	// are done because The proto expects count and time (nanoseconds) instead of count
   371	// and the number of cycles for block, contention profiles.
   372	// Possible 'scaler' functions are scaleBlockProfile and scaleMutexProfile.
   373	func printCountCycleProfile(w io.Writer, countName, cycleName string, scaler func(int64, float64) (int64, float64), records []runtime.BlockProfileRecord) error {
   374		// Output profile in protobuf form.
   375		b := newProfileBuilder(w)
   376		b.pbValueType(tagProfile_PeriodType, countName, "count")
   377		b.pb.int64Opt(tagProfile_Period, 1)
   378		b.pbValueType(tagProfile_SampleType, countName, "count")
   379		b.pbValueType(tagProfile_SampleType, cycleName, "nanoseconds")
   380	
   381		cpuGHz := float64(runtime_cyclesPerSecond()) / 1e9
   382	
   383		values := []int64{0, 0}
   384		var locs []uint64
   385		for _, r := range records {
   386			count, nanosec := scaler(r.Count, float64(r.Cycles)/cpuGHz)
   387			values[0] = count
   388			values[1] = int64(nanosec)
   389			locs = locs[:0]
   390			for _, addr := range r.Stack() {
   391				// For count profiles, all stack addresses are
   392				// return PCs, which is what locForPC expects.
   393				l := b.locForPC(addr)
   394				if l == 0 { // runtime.goexit
   395					continue
   396				}
   397				locs = append(locs, l)
   398			}
   399			b.pbSample(values, locs, nil)
   400		}
   401		b.build()
   402		return nil
   403	}
   404	
   405	// printCountProfile prints a countProfile at the specified debug level.
   406	// The profile will be in compressed proto format unless debug is nonzero.
   407	func printCountProfile(w io.Writer, debug int, name string, p countProfile) error {
   408		// Build count of each stack.
   409		var buf bytes.Buffer
   410		key := func(stk []uintptr) string {
   411			buf.Reset()
   412			fmt.Fprintf(&buf, "@")
   413			for _, pc := range stk {
   414				fmt.Fprintf(&buf, " %#x", pc)
   415			}
   416			return buf.String()
   417		}
   418		count := map[string]int{}
   419		index := map[string]int{}
   420		var keys []string
   421		n := p.Len()
   422		for i := 0; i < n; i++ {
   423			k := key(p.Stack(i))
   424			if count[k] == 0 {
   425				index[k] = i
   426				keys = append(keys, k)
   427			}
   428			count[k]++
   429		}
   430	
   431		sort.Sort(&keysByCount{keys, count})
   432	
   433		if debug > 0 {
   434			// Print debug profile in legacy format
   435			tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
   436			fmt.Fprintf(tw, "%s profile: total %d\n", name, p.Len())
   437			for _, k := range keys {
   438				fmt.Fprintf(tw, "%d %s\n", count[k], k)
   439				printStackRecord(tw, p.Stack(index[k]), false)
   440			}
   441			return tw.Flush()
   442		}
   443	
   444		// Output profile in protobuf form.
   445		b := newProfileBuilder(w)
   446		b.pbValueType(tagProfile_PeriodType, name, "count")
   447		b.pb.int64Opt(tagProfile_Period, 1)
   448		b.pbValueType(tagProfile_SampleType, name, "count")
   449	
   450		values := []int64{0}
   451		var locs []uint64
   452		for _, k := range keys {
   453			values[0] = int64(count[k])
   454			locs = locs[:0]
   455			for _, addr := range p.Stack(index[k]) {
   456				// For count profiles, all stack addresses are
   457				// return PCs, which is what locForPC expects.
   458				l := b.locForPC(addr)
   459				if l == 0 { // runtime.goexit
   460					continue
   461				}
   462				locs = append(locs, l)
   463			}
   464			b.pbSample(values, locs, nil)
   465		}
   466		b.build()
   467		return nil
   468	}
   469	
   470	// keysByCount sorts keys with higher counts first, breaking ties by key string order.
   471	type keysByCount struct {
   472		keys  []string
   473		count map[string]int
   474	}
   475	
   476	func (x *keysByCount) Len() int      { return len(x.keys) }
   477	func (x *keysByCount) Swap(i, j int) { x.keys[i], x.keys[j] = x.keys[j], x.keys[i] }
   478	func (x *keysByCount) Less(i, j int) bool {
   479		ki, kj := x.keys[i], x.keys[j]
   480		ci, cj := x.count[ki], x.count[kj]
   481		if ci != cj {
   482			return ci > cj
   483		}
   484		return ki < kj
   485	}
   486	
   487	// printStackRecord prints the function + source line information
   488	// for a single stack trace.
   489	func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
   490		show := allFrames
   491		frames := runtime.CallersFrames(stk)
   492		for {
   493			frame, more := frames.Next()
   494			name := frame.Function
   495			if name == "" {
   496				show = true
   497				fmt.Fprintf(w, "#\t%#x\n", frame.PC)
   498			} else if name != "runtime.goexit" && (show || !strings.HasPrefix(name, "runtime.")) {
   499				// Hide runtime.goexit and any runtime functions at the beginning.
   500				// This is useful mainly for allocation traces.
   501				show = true
   502				fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", frame.PC, name, frame.PC-frame.Entry, frame.File, frame.Line)
   503			}
   504			if !more {
   505				break
   506			}
   507		}
   508		if !show {
   509			// We didn't print anything; do it again,
   510			// and this time include runtime functions.
   511			printStackRecord(w, stk, true)
   512			return
   513		}
   514		fmt.Fprintf(w, "\n")
   515	}
   516	
   517	// Interface to system profiles.
   518	
   519	// WriteHeapProfile is shorthand for Lookup("heap").WriteTo(w, 0).
   520	// It is preserved for backwards compatibility.
   521	func WriteHeapProfile(w io.Writer) error {
   522		return writeHeap(w, 0)
   523	}
   524	
   525	// countHeap returns the number of records in the heap profile.
   526	func countHeap() int {
   527		n, _ := runtime.MemProfile(nil, true)
   528		return n
   529	}
   530	
   531	// writeHeap writes the current runtime heap profile to w.
   532	func writeHeap(w io.Writer, debug int) error {
   533		return writeHeapInternal(w, debug, "")
   534	}
   535	
   536	// writeAlloc writes the current runtime heap profile to w
   537	// with the total allocation space as the default sample type.
   538	func writeAlloc(w io.Writer, debug int) error {
   539		return writeHeapInternal(w, debug, "alloc_space")
   540	}
   541	
   542	func writeHeapInternal(w io.Writer, debug int, defaultSampleType string) error {
   543		var memStats *runtime.MemStats
   544		if debug != 0 {
   545			// Read mem stats first, so that our other allocations
   546			// do not appear in the statistics.
   547			memStats = new(runtime.MemStats)
   548			runtime.ReadMemStats(memStats)
   549		}
   550	
   551		// Find out how many records there are (MemProfile(nil, true)),
   552		// allocate that many records, and get the data.
   553		// There's a race—more records might be added between
   554		// the two calls—so allocate a few extra records for safety
   555		// and also try again if we're very unlucky.
   556		// The loop should only execute one iteration in the common case.
   557		var p []runtime.MemProfileRecord
   558		n, ok := runtime.MemProfile(nil, true)
   559		for {
   560			// Allocate room for a slightly bigger profile,
   561			// in case a few more entries have been added
   562			// since the call to MemProfile.
   563			p = make([]runtime.MemProfileRecord, n+50)
   564			n, ok = runtime.MemProfile(p, true)
   565			if ok {
   566				p = p[0:n]
   567				break
   568			}
   569			// Profile grew; try again.
   570		}
   571	
   572		if debug == 0 {
   573			return writeHeapProto(w, p, int64(runtime.MemProfileRate), defaultSampleType)
   574		}
   575	
   576		sort.Slice(p, func(i, j int) bool { return p[i].InUseBytes() > p[j].InUseBytes() })
   577	
   578		b := bufio.NewWriter(w)
   579		tw := tabwriter.NewWriter(b, 1, 8, 1, '\t', 0)
   580		w = tw
   581	
   582		var total runtime.MemProfileRecord
   583		for i := range p {
   584			r := &p[i]
   585			total.AllocBytes += r.AllocBytes
   586			total.AllocObjects += r.AllocObjects
   587			total.FreeBytes += r.FreeBytes
   588			total.FreeObjects += r.FreeObjects
   589		}
   590	
   591		// Technically the rate is MemProfileRate not 2*MemProfileRate,
   592		// but early versions of the C++ heap profiler reported 2*MemProfileRate,
   593		// so that's what pprof has come to expect.
   594		fmt.Fprintf(w, "heap profile: %d: %d [%d: %d] @ heap/%d\n",
   595			total.InUseObjects(), total.InUseBytes(),
   596			total.AllocObjects, total.AllocBytes,
   597			2*runtime.MemProfileRate)
   598	
   599		for i := range p {
   600			r := &p[i]
   601			fmt.Fprintf(w, "%d: %d [%d: %d] @",
   602				r.InUseObjects(), r.InUseBytes(),
   603				r.AllocObjects, r.AllocBytes)
   604			for _, pc := range r.Stack() {
   605				fmt.Fprintf(w, " %#x", pc)
   606			}
   607			fmt.Fprintf(w, "\n")
   608			printStackRecord(w, r.Stack(), false)
   609		}
   610	
   611		// Print memstats information too.
   612		// Pprof will ignore, but useful for people
   613		s := memStats
   614		fmt.Fprintf(w, "\n# runtime.MemStats\n")
   615		fmt.Fprintf(w, "# Alloc = %d\n", s.Alloc)
   616		fmt.Fprintf(w, "# TotalAlloc = %d\n", s.TotalAlloc)
   617		fmt.Fprintf(w, "# Sys = %d\n", s.Sys)
   618		fmt.Fprintf(w, "# Lookups = %d\n", s.Lookups)
   619		fmt.Fprintf(w, "# Mallocs = %d\n", s.Mallocs)
   620		fmt.Fprintf(w, "# Frees = %d\n", s.Frees)
   621	
   622		fmt.Fprintf(w, "# HeapAlloc = %d\n", s.HeapAlloc)
   623		fmt.Fprintf(w, "# HeapSys = %d\n", s.HeapSys)
   624		fmt.Fprintf(w, "# HeapIdle = %d\n", s.HeapIdle)
   625		fmt.Fprintf(w, "# HeapInuse = %d\n", s.HeapInuse)
   626		fmt.Fprintf(w, "# HeapReleased = %d\n", s.HeapReleased)
   627		fmt.Fprintf(w, "# HeapObjects = %d\n", s.HeapObjects)
   628	
   629		fmt.Fprintf(w, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
   630		fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
   631		fmt.Fprintf(w, "# MCache = %d / %d\n", s.MCacheInuse, s.MCacheSys)
   632		fmt.Fprintf(w, "# BuckHashSys = %d\n", s.BuckHashSys)
   633		fmt.Fprintf(w, "# GCSys = %d\n", s.GCSys)
   634		fmt.Fprintf(w, "# OtherSys = %d\n", s.OtherSys)
   635	
   636		fmt.Fprintf(w, "# NextGC = %d\n", s.NextGC)
   637		fmt.Fprintf(w, "# LastGC = %d\n", s.LastGC)
   638		fmt.Fprintf(w, "# PauseNs = %d\n", s.PauseNs)
   639		fmt.Fprintf(w, "# PauseEnd = %d\n", s.PauseEnd)
   640		fmt.Fprintf(w, "# NumGC = %d\n", s.NumGC)
   641		fmt.Fprintf(w, "# NumForcedGC = %d\n", s.NumForcedGC)
   642		fmt.Fprintf(w, "# GCCPUFraction = %v\n", s.GCCPUFraction)
   643		fmt.Fprintf(w, "# DebugGC = %v\n", s.DebugGC)
   644	
   645		tw.Flush()
   646		return b.Flush()
   647	}
   648	
   649	// countThreadCreate returns the size of the current ThreadCreateProfile.
   650	func countThreadCreate() int {
   651		n, _ := runtime.ThreadCreateProfile(nil)
   652		return n
   653	}
   654	
   655	// writeThreadCreate writes the current runtime ThreadCreateProfile to w.
   656	func writeThreadCreate(w io.Writer, debug int) error {
   657		return writeRuntimeProfile(w, debug, "threadcreate", runtime.ThreadCreateProfile)
   658	}
   659	
   660	// countGoroutine returns the number of goroutines.
   661	func countGoroutine() int {
   662		return runtime.NumGoroutine()
   663	}
   664	
   665	// writeGoroutine writes the current runtime GoroutineProfile to w.
   666	func writeGoroutine(w io.Writer, debug int) error {
   667		if debug >= 2 {
   668			return writeGoroutineStacks(w)
   669		}
   670		return writeRuntimeProfile(w, debug, "goroutine", runtime.GoroutineProfile)
   671	}
   672	
   673	func writeGoroutineStacks(w io.Writer) error {
   674		// We don't know how big the buffer needs to be to collect
   675		// all the goroutines. Start with 1 MB and try a few times, doubling each time.
   676		// Give up and use a truncated trace if 64 MB is not enough.
   677		buf := make([]byte, 1<<20)
   678		for i := 0; ; i++ {
   679			n := runtime.Stack(buf, true)
   680			if n < len(buf) {
   681				buf = buf[:n]
   682				break
   683			}
   684			if len(buf) >= 64<<20 {
   685				// Filled 64 MB - stop there.
   686				break
   687			}
   688			buf = make([]byte, 2*len(buf))
   689		}
   690		_, err := w.Write(buf)
   691		return err
   692	}
   693	
   694	func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runtime.StackRecord) (int, bool)) error {
   695		// Find out how many records there are (fetch(nil)),
   696		// allocate that many records, and get the data.
   697		// There's a race—more records might be added between
   698		// the two calls—so allocate a few extra records for safety
   699		// and also try again if we're very unlucky.
   700		// The loop should only execute one iteration in the common case.
   701		var p []runtime.StackRecord
   702		n, ok := fetch(nil)
   703		for {
   704			// Allocate room for a slightly bigger profile,
   705			// in case a few more entries have been added
   706			// since the call to ThreadProfile.
   707			p = make([]runtime.StackRecord, n+10)
   708			n, ok = fetch(p)
   709			if ok {
   710				p = p[0:n]
   711				break
   712			}
   713			// Profile grew; try again.
   714		}
   715	
   716		return printCountProfile(w, debug, name, runtimeProfile(p))
   717	}
   718	
   719	type runtimeProfile []runtime.StackRecord
   720	
   721	func (p runtimeProfile) Len() int              { return len(p) }
   722	func (p runtimeProfile) Stack(i int) []uintptr { return p[i].Stack() }
   723	
   724	var cpu struct {
   725		sync.Mutex
   726		profiling bool
   727		done      chan bool
   728	}
   729	
   730	// StartCPUProfile enables CPU profiling for the current process.
   731	// While profiling, the profile will be buffered and written to w.
   732	// StartCPUProfile returns an error if profiling is already enabled.
   733	//
   734	// On Unix-like systems, StartCPUProfile does not work by default for
   735	// Go code built with -buildmode=c-archive or -buildmode=c-shared.
   736	// StartCPUProfile relies on the SIGPROF signal, but that signal will
   737	// be delivered to the main program's SIGPROF signal handler (if any)
   738	// not to the one used by Go. To make it work, call os/signal.Notify
   739	// for syscall.SIGPROF, but note that doing so may break any profiling
   740	// being done by the main program.
   741	func StartCPUProfile(w io.Writer) error {
   742		// The runtime routines allow a variable profiling rate,
   743		// but in practice operating systems cannot trigger signals
   744		// at more than about 500 Hz, and our processing of the
   745		// signal is not cheap (mostly getting the stack trace).
   746		// 100 Hz is a reasonable choice: it is frequent enough to
   747		// produce useful data, rare enough not to bog down the
   748		// system, and a nice round number to make it easy to
   749		// convert sample counts to seconds. Instead of requiring
   750		// each client to specify the frequency, we hard code it.
   751		const hz = 100
   752	
   753		cpu.Lock()
   754		defer cpu.Unlock()
   755		if cpu.done == nil {
   756			cpu.done = make(chan bool)
   757		}
   758		// Double-check.
   759		if cpu.profiling {
   760			return fmt.Errorf("cpu profiling already in use")
   761		}
   762		cpu.profiling = true
   763		runtime.SetCPUProfileRate(hz)
   764		go profileWriter(w)
   765		return nil
   766	}
   767	
   768	// readProfile, provided by the runtime, returns the next chunk of
   769	// binary CPU profiling stack trace data, blocking until data is available.
   770	// If profiling is turned off and all the profile data accumulated while it was
   771	// on has been returned, readProfile returns eof=true.
   772	// The caller must save the returned data and tags before calling readProfile again.
   773	func readProfile() (data []uint64, tags []unsafe.Pointer, eof bool)
   774	
   775	func profileWriter(w io.Writer) {
   776		b := newProfileBuilder(w)
   777		var err error
   778		for {
   779			time.Sleep(100 * time.Millisecond)
   780			data, tags, eof := readProfile()
   781			if e := b.addCPUData(data, tags); e != nil && err == nil {
   782				err = e
   783			}
   784			if eof {
   785				break
   786			}
   787		}
   788		if err != nil {
   789			// The runtime should never produce an invalid or truncated profile.
   790			// It drops records that can't fit into its log buffers.
   791			panic("runtime/pprof: converting profile: " + err.Error())
   792		}
   793		b.build()
   794		cpu.done <- true
   795	}
   796	
   797	// StopCPUProfile stops the current CPU profile, if any.
   798	// StopCPUProfile only returns after all the writes for the
   799	// profile have completed.
   800	func StopCPUProfile() {
   801		cpu.Lock()
   802		defer cpu.Unlock()
   803	
   804		if !cpu.profiling {
   805			return
   806		}
   807		cpu.profiling = false
   808		runtime.SetCPUProfileRate(0)
   809		<-cpu.done
   810	}
   811	
   812	// countBlock returns the number of records in the blocking profile.
   813	func countBlock() int {
   814		n, _ := runtime.BlockProfile(nil)
   815		return n
   816	}
   817	
   818	// countMutex returns the number of records in the mutex profile.
   819	func countMutex() int {
   820		n, _ := runtime.MutexProfile(nil)
   821		return n
   822	}
   823	
   824	// writeBlock writes the current blocking profile to w.
   825	func writeBlock(w io.Writer, debug int) error {
   826		var p []runtime.BlockProfileRecord
   827		n, ok := runtime.BlockProfile(nil)
   828		for {
   829			p = make([]runtime.BlockProfileRecord, n+50)
   830			n, ok = runtime.BlockProfile(p)
   831			if ok {
   832				p = p[:n]
   833				break
   834			}
   835		}
   836	
   837		sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
   838	
   839		if debug <= 0 {
   840			return printCountCycleProfile(w, "contentions", "delay", scaleBlockProfile, p)
   841		}
   842	
   843		b := bufio.NewWriter(w)
   844		tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
   845		w = tw
   846	
   847		fmt.Fprintf(w, "--- contention:\n")
   848		fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
   849		for i := range p {
   850			r := &p[i]
   851			fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
   852			for _, pc := range r.Stack() {
   853				fmt.Fprintf(w, " %#x", pc)
   854			}
   855			fmt.Fprint(w, "\n")
   856			if debug > 0 {
   857				printStackRecord(w, r.Stack(), true)
   858			}
   859		}
   860	
   861		if tw != nil {
   862			tw.Flush()
   863		}
   864		return b.Flush()
   865	}
   866	
   867	func scaleBlockProfile(cnt int64, ns float64) (int64, float64) {
   868		// Do nothing.
   869		// The current way of block profile sampling makes it
   870		// hard to compute the unsampled number. The legacy block
   871		// profile parse doesn't attempt to scale or unsample.
   872		return cnt, ns
   873	}
   874	
   875	// writeMutex writes the current mutex profile to w.
   876	func writeMutex(w io.Writer, debug int) error {
   877		// TODO(pjw): too much common code with writeBlock. FIX!
   878		var p []runtime.BlockProfileRecord
   879		n, ok := runtime.MutexProfile(nil)
   880		for {
   881			p = make([]runtime.BlockProfileRecord, n+50)
   882			n, ok = runtime.MutexProfile(p)
   883			if ok {
   884				p = p[:n]
   885				break
   886			}
   887		}
   888	
   889		sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
   890	
   891		if debug <= 0 {
   892			return printCountCycleProfile(w, "contentions", "delay", scaleMutexProfile, p)
   893		}
   894	
   895		b := bufio.NewWriter(w)
   896		tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
   897		w = tw
   898	
   899		fmt.Fprintf(w, "--- mutex:\n")
   900		fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
   901		fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1))
   902		for i := range p {
   903			r := &p[i]
   904			fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
   905			for _, pc := range r.Stack() {
   906				fmt.Fprintf(w, " %#x", pc)
   907			}
   908			fmt.Fprint(w, "\n")
   909			if debug > 0 {
   910				printStackRecord(w, r.Stack(), true)
   911			}
   912		}
   913	
   914		if tw != nil {
   915			tw.Flush()
   916		}
   917		return b.Flush()
   918	}
   919	
   920	func scaleMutexProfile(cnt int64, ns float64) (int64, float64) {
   921		period := runtime.SetMutexProfileFraction(-1)
   922		return cnt * int64(period), ns * float64(period)
   923	}
   924	
   925	func runtime_cyclesPerSecond() int64
   926	

View as plain text