Skip to content

Commit

Permalink
plotting: make it possible to create CSV files
Browse files Browse the repository at this point in the history
  • Loading branch information
johningve committed Aug 29, 2021
1 parent d4b4fb5 commit dc46af0
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .vscode/dict.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@ unittests
unmarshals
wcfg
wrfs
xlabel
xyer
ylabel
12 changes: 11 additions & 1 deletion metrics/plotting/clientlatency.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package plotting

import (
"fmt"
"path"
"time"

"github.com/relab/hotstuff/metrics/types"
Expand Down Expand Up @@ -43,7 +44,16 @@ func (p *ClientLatencyPlot) Add(measurement interface{}) {

// PlotAverage plots the average latency of all clients within each measurement interval.
func (p *ClientLatencyPlot) PlotAverage(filename string, measurementInterval time.Duration) (err error) {
return GonumPlot(filename, "Time (seconds)", "Latency (ms)", func(plt *plot.Plot) error {
const (
xlabel = "Time (seconds)"
ylabel = "Latency (ms)"
)
if path.Ext(filename) == ".csv" {
return CSVPlot(filename, []string{xlabel, ylabel}, func() plotter.XYer {
return avgLatency(p, measurementInterval)
})
}
return GonumPlot(filename, xlabel, ylabel, func(plt *plot.Plot) error {
// TODO: error bars
if err := plotutil.AddLinePoints(plt, avgLatency(p, measurementInterval)); err != nil {
return fmt.Errorf("failed to add line plot: %w", err)
Expand Down
25 changes: 25 additions & 0 deletions metrics/plotting/helper.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package plotting

import (
"encoding/csv"
"fmt"
"image/color"
"os"
"time"

"github.com/relab/hotstuff/metrics/types"
Expand Down Expand Up @@ -165,3 +167,26 @@ func (xy xyer) XY(i int) (x float64, y float64) {
p := xy[i]
return p.x, p.y
}

// CSVPlot writes to a CSV file.
func CSVPlot(filename string, headers []string, plot func() plotter.XYer) error {
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
wr := csv.NewWriter(f)
err = wr.Write(headers)
if err != nil {
return err
}
xyer := plot()
for i := 0; i < xyer.Len(); i++ {
x, y := xyer.XY(i)
err = wr.Write([]string{fmt.Sprint(x), fmt.Sprint(y)})
if err != nil {
return err
}
}
wr.Flush()
return f.Close()
}
12 changes: 11 additions & 1 deletion metrics/plotting/throughput.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package plotting

import (
"fmt"
"path"
"time"

"github.com/relab/hotstuff/metrics/types"
Expand Down Expand Up @@ -44,7 +45,16 @@ func (p *ThroughputPlot) Add(measurement interface{}) {

// PlotAverage plots the average throughput of all replicas at specified time intervals.
func (p *ThroughputPlot) PlotAverage(filename string, measurementInterval time.Duration) (err error) {
return GonumPlot(filename, "Time (seconds)", "Throughput (commands/second)", func(plt *plot.Plot) 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)
}
Expand Down
12 changes: 11 additions & 1 deletion metrics/plotting/throughputvslatency.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package plotting

import (
"fmt"
"path"
"time"

"github.com/relab/hotstuff/metrics/types"
Expand Down Expand Up @@ -53,7 +54,16 @@ func (p *ThroughputVSLatencyPlot) Add(measurement interface{}) {

// PlotAverage plots the average throughput of all replicas at specified time intervals.
func (p *ThroughputVSLatencyPlot) PlotAverage(filename string, measurementInterval time.Duration) (err error) {
return GonumPlot(filename, "Throughput (commands/second)", "Latency (ms)", func(plt *plot.Plot) error {
const (
xlabel = "Throughput (commands/second)"
ylabel = "Latency (ms)"
)
if path.Ext(filename) == ".csv" {
return CSVPlot(filename, []string{xlabel, ylabel}, func() plotter.XYer {
return avgThroughputVSAvgLatency(p, measurementInterval)
})
}
return GonumPlot(filename, xlabel, ylabel, func(plt *plot.Plot) error {
if err := plotutil.AddScatters(plt, avgThroughputVSAvgLatency(p, measurementInterval)); err != nil {
return fmt.Errorf("failed to add scatter plot: %w", err)
}
Expand Down

0 comments on commit dc46af0

Please sign in to comment.