Home | History | Annotate | Download | only in debug
      1 // Copyright 2013 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 debug
      6 
      7 import (
      8 	"runtime"
      9 	"sort"
     10 	"time"
     11 )
     12 
     13 // GCStats collect information about recent garbage collections.
     14 type GCStats struct {
     15 	LastGC         time.Time       // time of last collection
     16 	NumGC          int64           // number of garbage collections
     17 	PauseTotal     time.Duration   // total pause for all collections
     18 	Pause          []time.Duration // pause history, most recent first
     19 	PauseEnd       []time.Time     // pause end times history, most recent first
     20 	PauseQuantiles []time.Duration
     21 }
     22 
     23 // ReadGCStats reads statistics about garbage collection into stats.
     24 // The number of entries in the pause history is system-dependent;
     25 // stats.Pause slice will be reused if large enough, reallocated otherwise.
     26 // ReadGCStats may use the full capacity of the stats.Pause slice.
     27 // If stats.PauseQuantiles is non-empty, ReadGCStats fills it with quantiles
     28 // summarizing the distribution of pause time. For example, if
     29 // len(stats.PauseQuantiles) is 5, it will be filled with the minimum,
     30 // 25%, 50%, 75%, and maximum pause times.
     31 func ReadGCStats(stats *GCStats) {
     32 	// Create a buffer with space for at least two copies of the
     33 	// pause history tracked by the runtime. One will be returned
     34 	// to the caller and the other will be used as transfer buffer
     35 	// for end times history and as a temporary buffer for
     36 	// computing quantiles.
     37 	const maxPause = len(((*runtime.MemStats)(nil)).PauseNs)
     38 	if cap(stats.Pause) < 2*maxPause+3 {
     39 		stats.Pause = make([]time.Duration, 2*maxPause+3)
     40 	}
     41 
     42 	// readGCStats fills in the pause and end times histories (up to
     43 	// maxPause entries) and then three more: Unix ns time of last GC,
     44 	// number of GC, and total pause time in nanoseconds. Here we
     45 	// depend on the fact that time.Duration's native unit is
     46 	// nanoseconds, so the pauses and the total pause time do not need
     47 	// any conversion.
     48 	readGCStats(&stats.Pause)
     49 	n := len(stats.Pause) - 3
     50 	stats.LastGC = time.Unix(0, int64(stats.Pause[n]))
     51 	stats.NumGC = int64(stats.Pause[n+1])
     52 	stats.PauseTotal = stats.Pause[n+2]
     53 	n /= 2 // buffer holds pauses and end times
     54 	stats.Pause = stats.Pause[:n]
     55 
     56 	if cap(stats.PauseEnd) < maxPause {
     57 		stats.PauseEnd = make([]time.Time, 0, maxPause)
     58 	}
     59 	stats.PauseEnd = stats.PauseEnd[:0]
     60 	for _, ns := range stats.Pause[n : n+n] {
     61 		stats.PauseEnd = append(stats.PauseEnd, time.Unix(0, int64(ns)))
     62 	}
     63 
     64 	if len(stats.PauseQuantiles) > 0 {
     65 		if n == 0 {
     66 			for i := range stats.PauseQuantiles {
     67 				stats.PauseQuantiles[i] = 0
     68 			}
     69 		} else {
     70 			// There's room for a second copy of the data in stats.Pause.
     71 			// See the allocation at the top of the function.
     72 			sorted := stats.Pause[n : n+n]
     73 			copy(sorted, stats.Pause)
     74 			sort.Sort(byDuration(sorted))
     75 			nq := len(stats.PauseQuantiles) - 1
     76 			for i := 0; i < nq; i++ {
     77 				stats.PauseQuantiles[i] = sorted[len(sorted)*i/nq]
     78 			}
     79 			stats.PauseQuantiles[nq] = sorted[len(sorted)-1]
     80 		}
     81 	}
     82 }
     83 
     84 type byDuration []time.Duration
     85 
     86 func (x byDuration) Len() int           { return len(x) }
     87 func (x byDuration) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
     88 func (x byDuration) Less(i, j int) bool { return x[i] < x[j] }
     89 
     90 // SetGCPercent sets the garbage collection target percentage:
     91 // a collection is triggered when the ratio of freshly allocated data
     92 // to live data remaining after the previous collection reaches this percentage.
     93 // SetGCPercent returns the previous setting.
     94 // The initial setting is the value of the GOGC environment variable
     95 // at startup, or 100 if the variable is not set.
     96 // A negative percentage disables garbage collection.
     97 func SetGCPercent(percent int) int {
     98 	old := setGCPercent(int32(percent))
     99 	runtime.GC()
    100 	return int(old)
    101 }
    102 
    103 // FreeOSMemory forces a garbage collection followed by an
    104 // attempt to return as much memory to the operating system
    105 // as possible. (Even if this is not called, the runtime gradually
    106 // returns memory to the operating system in a background task.)
    107 func FreeOSMemory() {
    108 	freeOSMemory()
    109 }
    110 
    111 // SetMaxStack sets the maximum amount of memory that
    112 // can be used by a single goroutine stack.
    113 // If any goroutine exceeds this limit while growing its stack,
    114 // the program crashes.
    115 // SetMaxStack returns the previous setting.
    116 // The initial setting is 1 GB on 64-bit systems, 250 MB on 32-bit systems.
    117 //
    118 // SetMaxStack is useful mainly for limiting the damage done by
    119 // goroutines that enter an infinite recursion. It only limits future
    120 // stack growth.
    121 func SetMaxStack(bytes int) int {
    122 	return setMaxStack(bytes)
    123 }
    124 
    125 // SetMaxThreads sets the maximum number of operating system
    126 // threads that the Go program can use. If it attempts to use more than
    127 // this many, the program crashes.
    128 // SetMaxThreads returns the previous setting.
    129 // The initial setting is 10,000 threads.
    130 //
    131 // The limit controls the number of operating system threads, not the number
    132 // of goroutines. A Go program creates a new thread only when a goroutine
    133 // is ready to run but all the existing threads are blocked in system calls, cgo calls,
    134 // or are locked to other goroutines due to use of runtime.LockOSThread.
    135 //
    136 // SetMaxThreads is useful mainly for limiting the damage done by
    137 // programs that create an unbounded number of threads. The idea is
    138 // to take down the program before it takes down the operating system.
    139 func SetMaxThreads(threads int) int {
    140 	return setMaxThreads(threads)
    141 }
    142 
    143 // SetPanicOnFault controls the runtime's behavior when a program faults
    144 // at an unexpected (non-nil) address. Such faults are typically caused by
    145 // bugs such as runtime memory corruption, so the default response is to crash
    146 // the program. Programs working with memory-mapped files or unsafe
    147 // manipulation of memory may cause faults at non-nil addresses in less
    148 // dramatic situations; SetPanicOnFault allows such programs to request
    149 // that the runtime trigger only a panic, not a crash.
    150 // SetPanicOnFault applies only to the current goroutine.
    151 // It returns the previous setting.
    152 func SetPanicOnFault(enabled bool) bool {
    153 	return setPanicOnFault(enabled)
    154 }
    155 
    156 // WriteHeapDump writes a description of the heap and the objects in
    157 // it to the given file descriptor.
    158 // The heap dump format is defined at https://golang.org/s/go13heapdump.
    159 func WriteHeapDump(fd uintptr)
    160