-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathgc_summary.go
159 lines (139 loc) · 3.57 KB
/
gc_summary.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package pprof
import (
"bytes"
"fmt"
"io"
"os"
"runtime"
"runtime/debug"
"time"
)
var startTime = time.Now()
// Shorthand for GCSummary().Save(file)
func SaveGCSummary(file string) error {
return GCSummary().Save(file)
}
// Shorthand for GCSummary().SaveCSV(file)
func SaveGCSummaryGCV(file string) error {
return GCSummary().SaveCSV(file)
}
type GCSummaryInfo struct {
NumGC int64
LastPause time.Duration
PauseAvg time.Duration
Overhead float64
Alloc uint64
Sys uint64
AllocRate uint64
Histogram1 time.Duration
Histogram2 time.Duration
Histogram3 time.Duration
}
// Get GC summary.
func GCSummary() *GCSummaryInfo {
gcstats := debug.GCStats{PauseQuantiles: make([]time.Duration, 100)}
debug.ReadGCStats(&gcstats)
memStats := runtime.MemStats{}
runtime.ReadMemStats(&memStats)
elapsed := time.Now().Sub(startTime)
summary := &GCSummaryInfo{
Alloc: memStats.Alloc,
Sys: memStats.Sys,
AllocRate: uint64(float64(memStats.TotalAlloc) / elapsed.Seconds()),
}
if gcstats.NumGC > 0 {
summary.NumGC = gcstats.NumGC
summary.LastPause = gcstats.Pause[0]
summary.PauseAvg = durationAvg(gcstats.Pause)
summary.Overhead = float64(gcstats.PauseTotal) / float64(elapsed) * 100
summary.Histogram1 = gcstats.PauseQuantiles[94]
summary.Histogram2 = gcstats.PauseQuantiles[98]
summary.Histogram3 = gcstats.PauseQuantiles[99]
}
return summary
}
// Humman readable string.
func (summary *GCSummaryInfo) String() string {
buffer := new(bytes.Buffer)
summary.Write(buffer)
return buffer.String()
}
// CSV string.
func (summary *GCSummaryInfo) CSV() string {
buffer := new(bytes.Buffer)
summary.WriteCSV(buffer)
return buffer.String()
}
// Write as humman readable format.
func (summary *GCSummaryInfo) Write(writer io.Writer) error {
_, err := fmt.Fprintf(writer,
"NumGC: %d, LastPause: %v, Pause(Avg): %v, Overhead: %3.2f%%, Alloc: %s, Sys: %s, Alloc(Rate): %s/s, Histogram: %v %v %v\n",
summary.NumGC,
summary.LastPause,
summary.PauseAvg,
summary.Overhead,
formatSize(summary.Alloc),
formatSize(summary.Sys),
formatSize(summary.AllocRate),
summary.Histogram1,
summary.Histogram2,
summary.Histogram3,
)
return err
}
// Save as human readable file.
func (summary *GCSummaryInfo) Save(file string) error {
f, err := os.Create(file)
if err != nil {
return err
}
defer f.Close()
return summary.Write(f)
}
// GC summary CSV column names.
const GCSummaryColumns = "NumGC,LastPause,Pause(Avg),Overhead,Alloc,Sys,Alloc(Rate),Histogram1,Histogram2,Histogram3"
// Write as CSV format.
func (summary *GCSummaryInfo) WriteCSV(writer io.Writer) error {
_, err := fmt.Fprintf(writer,
"%d,%d,%d,%3.2f,%d,%d,%d,%d,%d,%d\n",
summary.NumGC,
summary.LastPause,
summary.PauseAvg,
summary.Overhead,
summary.Alloc,
summary.Sys,
summary.AllocRate,
summary.Histogram1,
summary.Histogram2,
summary.Histogram3,
)
return err
}
// Save as CSV file.
func (summary *GCSummaryInfo) SaveCSV(file string) error {
f, err := os.Create(file)
if err != nil {
return err
}
defer f.Close()
return summary.WriteCSV(f)
}
func durationAvg(items []time.Duration) time.Duration {
var sum time.Duration
for _, item := range items {
sum += item
}
return time.Duration(int64(sum) / int64(len(items)))
}
func formatSize(bytes uint64) string {
switch {
case bytes < 1024:
return fmt.Sprintf("%dB", bytes)
case bytes < 1024*1024:
return fmt.Sprintf("%.2fK", float64(bytes)/1024)
case bytes < 1024*1024*1024:
return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024)
default:
return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024)
}
}