1
0
mirror of https://github.com/divan/expvarmon.git synced 2025-04-27 13:48:55 +08:00

Add stats for GC pauses

This commit is contained in:
Ivan Daniluk 2016-11-13 16:26:23 +01:00
parent b93e309f19
commit 0091befb37
3 changed files with 64 additions and 13 deletions

View File

@ -1,9 +1,15 @@
package main
import (
"math"
)
type Histogram struct {
Bins []Bin
Maxbins int
Total uint64
min, max uint64
}
type Bin struct {
@ -16,15 +22,24 @@ type Bin struct {
// should be sufficient.
func NewHistogram(n int) *Histogram {
return &Histogram{
Bins: make([]Bin, 0),
Bins: make([]Bin, 0, n),
Maxbins: n,
Total: 0,
min: math.MaxUint64,
}
}
func (h *Histogram) Add(n uint64) {
defer h.trim()
h.Total++
if n > h.max {
h.max = n
}
if n < h.min {
h.min = n
}
defer h.trim()
for i := range h.Bins {
if h.Bins[i].Value == n {
h.Bins[i].Count++
@ -45,17 +60,17 @@ func (h *Histogram) Add(n uint64) {
h.Bins = append(h.Bins, Bin{Count: 1, Value: n})
}
func (h *Histogram) Quantile(q uint64) int64 {
count := q * h.Total
func (h *Histogram) Quantile(q float64) int64 {
count := q * float64(h.Total)
for i := range h.Bins {
count -= h.Bins[i].Count
count -= float64(h.Bins[i].Count)
if count <= 0 {
return int64(h.Bins[i].Value)
}
}
return -1
return 0
}
// CDF returns the value of the cumulative distribution function
@ -86,6 +101,24 @@ func (h *Histogram) Mean() float64 {
return sum / float64(h.Total)
}
// Min returns the minimal recorder value.
func (h *Histogram) Min() uint64 {
if h.Total == 0 {
return 0
}
return h.min
}
// Max returns the maximum recorder value.
func (h *Histogram) Max() uint64 {
if h.Total == 0 {
return 0
}
return h.max
}
// Variance returns the variance of the distribution
func (h *Histogram) Variance() float64 {
if h.Total == 0 {

View File

@ -15,6 +15,7 @@ type TermUISingle struct {
Sparkline *termui.Sparklines
Pars []*termui.Par
BarChart *termui.BarChart
GCStats *termui.Par
BarChart2 *termui.BarChart
bins int // histograms' bins count
@ -85,6 +86,14 @@ func (t *TermUISingle) Init(data UIData) error {
bc.NumColor = termui.ColorBlack
return bc
}()
t.GCStats = func() *termui.Par {
p := termui.NewPar("")
p.Height = 4
p.Width = len("Max: 123ms") // example
p.HasBorder = false
p.TextFgColor = termui.ColorGreen
return p
}()
}
if data.HasGCIntervals {
@ -150,13 +159,19 @@ func (t *TermUISingle) Update(data UIData) {
labels := make([]string, 0, len(counts))
for i := 0; i < len(counts); i++ {
vals = append(vals, int(counts[i]))
d := roundDuration(time.Duration(values[i]))
d := round(time.Duration(values[i]))
labels = append(labels, d.String())
}
t.BarChart.Data = vals
t.BarChart.DataLabels = labels
t.BarChart.Border.Label = "GC Pauses (last 256)"
t.GCStats.Text = fmt.Sprintf("Min: %v\nAvg: %v\n95p: %v\nMax: %v",
round(time.Duration(hist.Min())),
round(time.Duration(hist.Mean())),
round(time.Duration(hist.Quantile(0.95))),
round(time.Duration(hist.Max())),
)
}
if data.HasGCIntervals {
@ -173,7 +188,7 @@ func (t *TermUISingle) Update(data UIData) {
labels := make([]string, 0, len(counts))
for i := 0; i < len(counts); i++ {
vals = append(vals, int(counts[i]))
d := roundDuration(time.Duration(values[i]))
d := round(time.Duration(values[i]))
labels = append(labels, d.String())
}
t.BarChart2.Data = vals
@ -186,7 +201,7 @@ func (t *TermUISingle) Update(data UIData) {
var widgets []termui.Bufferer
widgets = append(widgets, t.Title, t.Status, t.Sparkline)
if data.HasGCPauses {
widgets = append(widgets, t.BarChart)
widgets = append(widgets, t.BarChart, t.GCStats)
}
if data.HasGCIntervals {
widgets = append(widgets, t.BarChart2)
@ -263,6 +278,9 @@ func (t *TermUISingle) Relayout() {
t.BarChart.Height = h - calcHeight
t.BarChart.Y = th - t.BarChart.Height
t.BarChart.BarWidth = binWidth
t.GCStats.X = barchartWidth - t.GCStats.Width - 1
t.GCStats.Y = t.BarChart.Y + 1
}
if t.BarChart2 != nil {

6
var.go
View File

@ -129,7 +129,7 @@ type Duration struct {
func (v *Duration) Kind() VarKind { return KindDuration }
func (v *Duration) String() string {
return fmt.Sprintf("%s", roundDuration(time.Duration(v.dur)))
return fmt.Sprintf("%s", round(time.Duration(v.dur)))
}
func (v *Duration) Set(j *jason.Value) {
@ -331,8 +331,8 @@ func (v VarName) Kind() VarKind {
return KindDefault
}
// roundDuration removes unneeded precision from the String() output for time.Duration.
func roundDuration(d time.Duration) time.Duration {
// round removes unneeded precision from the String() output for time.Duration.
func round(d time.Duration) time.Duration {
r := time.Second
if d < time.Second {
r = time.Millisecond