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