-
Notifications
You must be signed in to change notification settings - Fork 53
/
throughput.go
71 lines (61 loc) · 1.89 KB
/
throughput.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
package plotting
import (
"fmt"
"path"
"time"
"github.com/relab/hotstuff/metrics/types"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/plotutil"
)
// ThroughputPlot is a plotter that plots throughput vs time.
type ThroughputPlot struct {
startTimes StartTimes
measurements MeasurementMap
}
// NewThroughputPlot returns a new throughput plotter.
func NewThroughputPlot() ThroughputPlot {
return ThroughputPlot{
startTimes: NewStartTimes(),
measurements: NewMeasurementMap(),
}
}
// Add adds a measurement to the plotter.
func (p *ThroughputPlot) Add(measurement interface{}) {
p.startTimes.Add(measurement)
throughput, ok := measurement.(*types.ThroughputMeasurement)
if !ok {
return
}
if throughput.GetEvent().GetClient() {
// ignoring client events
return
}
id := throughput.GetEvent().GetID()
p.measurements.Add(id, throughput)
}
// PlotAverage plots the average throughput of all replicas at specified time intervals.
func (p *ThroughputPlot) PlotAverage(filename string, measurementInterval time.Duration) (err error) {
const (
xlabel = "Time (seconds)"
ylabel = "Throughput (commands/second)"
)
if path.Ext(filename) == ".csv" {
return CSVPlot(filename, []string{xlabel, ylabel}, func() plotter.XYer {
return avgThroughput(p, measurementInterval)
})
}
return GonumPlot(filename, xlabel, ylabel, func(plt *plot.Plot) error {
if err := plotutil.AddLinePoints(plt, avgThroughput(p, measurementInterval)); err != nil {
return fmt.Errorf("failed to add line plot: %w", err)
}
return nil
})
}
func avgThroughput(p *ThroughputPlot, interval time.Duration) plotter.XYer {
intervals := GroupByTimeInterval(&p.startTimes, p.measurements, interval)
return TimeAndAverage(intervals, func(m Measurement) (float64, uint64) {
tp := m.(*types.ThroughputMeasurement)
return float64(tp.GetCommands()) / tp.GetDuration().AsDuration().Seconds(), 1
})
}