Add GC intervals

This commit is contained in:
Ivan Daniluk 2016-11-13 15:23:30 +01:00
parent 036e299988
commit b93e309f19
4 changed files with 170 additions and 37 deletions

16
data.go
View File

@ -10,8 +10,8 @@ type UIData struct {
SparklineData []*SparklineData
HasGCPauses bool
HasGCTimes bool
HasGCPauses bool
HasGCIntervals bool
}
// SparklineData holds additional data needed for sparklines.
@ -49,13 +49,21 @@ func NewUIData(vars []VarName, services []*Service) *UIData {
}
return false
}
hasGCIntervals := func(vars []VarName) bool {
for _, v := range vars {
if v.Kind() == KindGCIntervals {
return true
}
}
return false
}
return &UIData{
Services: services,
Vars: vars,
SparklineData: sp,
HasGCPauses: hasGCPauses(vars),
HasGCTimes: true,
HasGCPauses: hasGCPauses(vars),
HasGCIntervals: hasGCIntervals(vars),
}
}

View File

@ -76,23 +76,27 @@ func (t *TermUISingle) Init(data UIData) error {
return s
}()
t.BarChart = func() *termui.BarChart {
bc := termui.NewBarChart()
bc.Border.Label = "Bar Chart"
bc.TextColor = termui.ColorGreen
bc.BarColor = termui.ColorGreen
bc.NumColor = termui.ColorBlack
return bc
}()
if data.HasGCPauses {
t.BarChart = func() *termui.BarChart {
bc := termui.NewBarChart()
bc.Border.Label = "Bar Chart"
bc.TextColor = termui.ColorGreen
bc.BarColor = termui.ColorGreen
bc.NumColor = termui.ColorBlack
return bc
}()
}
t.BarChart2 = func() *termui.BarChart {
bc := termui.NewBarChart()
bc.Border.Label = "Bar Chart"
bc.TextColor = termui.ColorGreen
bc.BarColor = termui.ColorGreen
bc.NumColor = termui.ColorBlack
return bc
}()
if data.HasGCIntervals {
t.BarChart2 = func() *termui.BarChart {
bc := termui.NewBarChart()
bc.Border.Label = "Bar Chart"
bc.TextColor = termui.ColorGreen
bc.BarColor = termui.ColorGreen
bc.NumColor = termui.ColorBlack
return bc
}()
}
t.Relayout()
@ -153,9 +157,28 @@ func (t *TermUISingle) Update(data UIData) {
t.BarChart.DataLabels = labels
t.BarChart.Border.Label = "GC Pauses (last 256)"
}
if data.HasGCIntervals {
var gcintervals *GCIntervals
for _, v := range service.Vars {
if v.Kind() == KindGCIntervals {
gcintervals = v.(*GCIntervals)
break
}
}
hist := gcintervals.Histogram(t.bins)
values, counts := hist.BarchartData()
vals := make([]int, 0, len(counts))
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]))
labels = append(labels, d.String())
}
t.BarChart2.Data = vals
t.BarChart2.DataLabels = labels
t.BarChart2.Border.Label = "GC Pauses (last 256)"
t.BarChart2.Border.Label = "Intervals between GC (last 256)"
}
t.Relayout()
@ -165,7 +188,7 @@ func (t *TermUISingle) Update(data UIData) {
if data.HasGCPauses {
widgets = append(widgets, t.BarChart)
}
if data.HasGCTimes {
if data.HasGCIntervals {
widgets = append(widgets, t.BarChart2)
}
for _, par := range t.Pars {
@ -221,20 +244,35 @@ func (t *TermUISingle) Relayout() {
t.Sparkline.Height = calcHeight
t.Sparkline.Y = th - h
// Fourth row: Barchart
bins, binWidth := recalcBins(tw / 2)
t.bins = bins
// Fourth row: Barcharts
var barchartWidth, charts int
if t.BarChart != nil {
charts++
}
if t.BarChart2 != nil {
charts++
}
t.BarChart.Width = tw / 2
t.BarChart.Height = h - calcHeight
t.BarChart.Y = th - t.BarChart.Height
t.BarChart.BarWidth = binWidth
if charts > 0 {
barchartWidth = tw / charts
bins, binWidth := recalcBins(barchartWidth)
t.bins = bins
t.BarChart2.Width = tw / 2
t.BarChart2.X = tw / 2
t.BarChart2.Height = h - calcHeight
t.BarChart2.Y = th - t.BarChart.Height
t.BarChart2.BarWidth = binWidth
if t.BarChart != nil {
t.BarChart.Width = barchartWidth
t.BarChart.Height = h - calcHeight
t.BarChart.Y = th - t.BarChart.Height
t.BarChart.BarWidth = binWidth
}
if t.BarChart2 != nil {
t.BarChart2.Width = barchartWidth
t.BarChart2.X = 0 + barchartWidth
t.BarChart2.Height = h - calcHeight
t.BarChart2.Y = th - t.BarChart.Height
t.BarChart2.BarWidth = binWidth
}
}
}
// recalcBins attempts to select optimal value for the number

71
var.go
View File

@ -26,6 +26,7 @@ const (
KindDuration
KindString
KindGCPauses
KindGCIntervals
)
// Var represents arbitrary value for variable.
@ -57,6 +58,8 @@ func NewVar(name VarName) Var {
return &String{}
case KindGCPauses:
return &GCPauses{}
case KindGCIntervals:
return &GCIntervals{}
default:
return &Number{}
}
@ -204,7 +207,70 @@ func (v *GCPauses) Histogram(bins int) *Histogram {
return hist
}
// TODO: add boolean, timestamp, gcpauses, gcendtimes types
// GCIntervals represents GC pauses intervals.
//
// It uses memstat.PauseEnd circular buffer w/
// timestamps.
type GCIntervals struct {
intervals [256]uint64
}
func (v *GCIntervals) Kind() VarKind { return KindGCIntervals }
func (v *GCIntervals) String() string { return "" }
func (v *GCIntervals) Set(j *jason.Value) {
v.intervals = [256]uint64{}
if j == nil {
return
}
// as original array contains UNIX timestamps,
// we want to calculate diffs to previous values (interval)
// and work with them
duration := func(a, b int64) uint64 {
dur := int64(a - b)
if dur < 0 {
dur = -dur
}
return uint64(dur)
}
var prev int64
if arr, err := j.Array(); err == nil {
for i := 1; i < len(arr); i++ {
p, _ := arr[i].Int64()
v.intervals[i] = duration(p, prev)
prev = p
}
// process last and fist elems
p, _ := arr[0].Int64()
v.intervals[0] = duration(p, prev)
}
}
func (v *GCIntervals) Histogram(bins int) *Histogram {
hist := NewHistogram(bins)
// we need to skip maximum value here
// because it's always a diff between last and fist
// elem in cicrular buffer (we don't know NumGC)
var max uint64
for i := 0; i < 256; i++ {
if v.intervals[i] > max {
max = v.intervals[i]
}
}
for i := 0; i < 256; i++ {
// we ignore zeros, since
// its never the case, but
// we have zeros on the very beginning
if v.intervals[i] > 0 && v.intervals[i] != max {
hist.Add(v.intervals[i])
}
}
return hist
}
// TODO: add boolean, timestamp, types
// ToSlice converts "dot-separated" notation into the "slice of strings".
//
@ -245,6 +311,9 @@ func (v VarName) Kind() VarKind {
if v.Long() == "memstats.PauseNs" {
return KindGCPauses
}
if v.Long() == "memstats.PauseEnd" {
return KindGCIntervals
}
start := strings.IndexRune(string(v), ':')
if start == -1 {

File diff suppressed because one or more lines are too long