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.
13 // GCStats collect information about recent garbage collections.
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
22 // Implemented in package runtime.
23 func readGCStats(*[]time
.Duration
)
24 func enableGC(bool) bool
25 func setGCPercent(int) int
28 // ReadGCStats reads statistics about garbage collection into stats.
29 // The number of entries in the pause history is system-dependent;
30 // stats.Pause slice will be reused if large enough, reallocated otherwise.
31 // ReadGCStats may use the full capacity of the stats.Pause slice.
32 // If stats.PauseQuantiles is non-empty, ReadGCStats fills it with quantiles
33 // summarizing the distribution of pause time. For example, if
34 // len(stats.PauseQuantiles) is 5, it will be filled with the minimum,
35 // 25%, 50%, 75%, and maximum pause times.
36 func ReadGCStats(stats
*GCStats
) {
37 // Create a buffer with space for at least two copies of the
38 // pause history tracked by the runtime. One will be returned
39 // to the caller and the other will be used as a temporary buffer
40 // for computing quantiles.
41 const maxPause
= len(((*runtime
.MemStats
)(nil)).PauseNs
)
42 if cap(stats
.Pause
) < 2*maxPause
{
43 stats
.Pause
= make([]time
.Duration
, 2*maxPause
)
46 // readGCStats fills in the pause history (up to maxPause entries)
47 // and then three more: Unix ns time of last GC, number of GC,
48 // and total pause time in nanoseconds. Here we depend on the
49 // fact that time.Duration's native unit is nanoseconds, so the
50 // pauses and the total pause time do not need any conversion.
51 readGCStats(&stats
.Pause
)
52 n
:= len(stats
.Pause
) - 3
53 stats
.LastGC
= time
.Unix(0, int64(stats
.Pause
[n
]))
54 stats
.NumGC
= int64(stats
.Pause
[n
+1])
55 stats
.PauseTotal
= stats
.Pause
[n
+2]
56 stats
.Pause
= stats
.Pause
[:n
]
58 if len(stats
.PauseQuantiles
) > 0 {
60 for i
:= range stats
.PauseQuantiles
{
61 stats
.PauseQuantiles
[i
] = 0
64 // There's room for a second copy of the data in stats.Pause.
65 // See the allocation at the top of the function.
66 sorted
:= stats
.Pause
[n
: n
+n
]
67 copy(sorted
, stats
.Pause
)
68 sort
.Sort(byDuration(sorted
))
69 nq
:= len(stats
.PauseQuantiles
) - 1
70 for i
:= 0; i
< nq
; i
++ {
71 stats
.PauseQuantiles
[i
] = sorted
[len(sorted
)*i
/nq
]
73 stats
.PauseQuantiles
[nq
] = sorted
[len(sorted
)-1]
78 type byDuration
[]time
.Duration
80 func (x byDuration
) Len() int { return len(x
) }
81 func (x byDuration
) Swap(i
, j
int) { x
[i
], x
[j
] = x
[j
], x
[i
] }
82 func (x byDuration
) Less(i
, j
int) bool { return x
[i
] < x
[j
] }
84 // SetGCPercent sets the garbage collection target percentage:
85 // a collection is triggered when the ratio of freshly allocated data
86 // to live data remaining after the previous collection reaches this percentage.
87 // SetGCPercent returns the previous setting.
88 // The initial setting is the value of the GOGC environment variable
89 // at startup, or 100 if the variable is not set.
90 // A negative percentage disables garbage collection.
91 func SetGCPercent(percent
int) int {
92 return setGCPercent(percent
)
95 // FreeOSMemory forces a garbage collection followed by an
96 // attempt to return as much memory to the operating system
97 // as possible. (Even if this is not called, the runtime gradually
98 // returns memory to the operating system in a background task.)