forked from cloudfoundry-incubator/pat
/
cmdline.go
141 lines (121 loc) · 5.4 KB
/
cmdline.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
package pat
import (
"fmt"
"os"
"strings"
"github.com/julz/pat/benchmarker"
"github.com/julz/pat/config"
. "github.com/julz/pat/experiment"
"github.com/julz/pat/experiments"
. "github.com/julz/pat/laboratory"
"github.com/julz/pat/store"
)
type Response struct {
TotalTime int64
Timestamp int64
}
var params = struct {
iterations int
concurrency int
silent bool
output string
workload string
interval int
stop int
csvDir string
}{}
var restContext = experiments.NewContext()
func InitCommandLineFlags(config config.Config) {
config.IntVar(¶ms.iterations, "iterations", 1, "number of pushes to attempt")
config.IntVar(¶ms.concurrency, "concurrency", 1, "max number of pushes to attempt in parallel")
config.BoolVar(¶ms.silent, "silent", false, "true to run the commands and print output the terminal")
config.StringVar(¶ms.output, "output", "", "if specified, writes benchmark results to a CSV file")
config.StringVar(¶ms.workload, "workload", "", "The set of operations a user should issue (ex. login,push,push)")
config.IntVar(¶ms.interval, "interval", 0, "repeat a workload at n second interval, to be used with -stop")
config.IntVar(¶ms.stop, "stop", 0, "stop a repeating interval after n second, to be used with -interval")
config.StringVar(¶ms.csvDir, "csvDir", "output/csvs", "Directory to Store CSVs")
restContext.DescribeParameters(config)
}
func RunCommandLine() error {
lab := NewLaboratory(store.NewCsvStore("output/csvs"))
worker := benchmarker.NewWorker()
err := RunCommandLineWithLabAndWorker(lab, worker)
for {
in := make([]byte, 1)
os.Stdin.Read(in)
if string(in) == "q" {
return err
}
}
}
func RunCommandLineWithLabAndWorker(lab Laboratory, worker benchmarker.Worker) (err error) {
handlers := make([]func(<-chan *Sample), 0)
if !params.silent {
handlers = append(handlers, func(s <-chan *Sample) {
display(params.concurrency, params.iterations, params.interval, params.stop, s)
})
}
rest := restContext
worker.AddExperiment("rest:login", rest.Login)
worker.AddExperiment("rest:push", rest.Push)
worker.AddExperiment("rest:target", rest.Target)
worker.AddExperiment("gcf:push", experiments.Push)
worker.AddExperiment("dummy", experiments.Dummy)
worker.AddExperiment("dummyWithErrors", experiments.DummyWithErrors)
lab.RunWithHandlers(
NewRunnableExperiment(
NewExperimentConfiguration(
params.iterations, params.concurrency, params.interval, params.stop, worker, params.workload)), handlers)
return nil
}
func display(concurrency int, iterations int, interval int, stop int, samples <-chan *Sample) {
for s := range samples {
fmt.Print("\033[2J\033[;H")
fmt.Println("\x1b[32;1mCloud Foundry Performance Acceptance Tests\x1b[0m")
fmt.Printf("Test underway. Concurrency: \x1b[36m%v\x1b[0m Workload iterations: \x1b[36m%v\x1b[0m Interval: \x1b[36m%v\x1b[0m Stop: \x1b[36m%v\x1b[0m\n", concurrency, iterations, interval, stop)
fmt.Println("┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄\n")
fmt.Printf("\x1b[36mTotal iterations\x1b[0m: %v \x1b[36m%v\x1b[0m / %v\n", bar(s.Total, totalIterations(iterations, interval, stop), 25), s.Total, totalIterations(iterations, interval, stop))
fmt.Println()
fmt.Printf("\x1b[1mLatest iteration\x1b[0m: \x1b[36m%v\x1b[0m\n", s.LastResult)
fmt.Printf("\x1b[1mWorst iteration\x1b[0m: \x1b[36m%v\x1b[0m\n", s.WorstResult)
fmt.Printf("\x1b[1mAverage iteration\x1b[0m: \x1b[36m%v\x1b[0m\n", s.Average)
fmt.Printf("\x1b[1mTotal time\x1b[0m: \x1b[36m%v\x1b[0m\n", s.TotalTime)
fmt.Printf("\x1b[1mWall time\x1b[0m: \x1b[36m%v\x1b[0m\n", s.WallTime)
fmt.Printf("\x1b[1mRunning Workers\x1b[0m: \x1b[36m%v\x1b[0m\n", s.TotalWorkers)
fmt.Println()
fmt.Println("\x1b[32;1mCommands Issued:\x1b[0m")
fmt.Println()
for key, command := range s.Commands {
fmt.Printf("\x1b[1m%v\x1b[0m:\n", key)
fmt.Printf("\x1b[1m\tCount\x1b[0m: \x1b[36m%v\x1b[0m\n", command.Count)
fmt.Printf("\x1b[1m\tAverage\x1b[0m: \x1b[36m%v\x1b[0m\n", command.Average)
fmt.Printf("\x1b[1m\tLast time\x1b[0m: \x1b[36m%v\x1b[0m\n", command.LastTime)
fmt.Printf("\x1b[1m\tWorst time\x1b[0m: \x1b[36m%v\x1b[0m\n", command.WorstTime)
fmt.Printf("\x1b[1m\tTotal time\x1b[0m: \x1b[36m%v\x1b[0m\n", command.TotalTime)
fmt.Printf("\x1b[1m\tPer second throughput\x1b[0m: \x1b[36m%v\x1b[0m\n", command.Throughput)
}
fmt.Println("┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")
if s.TotalErrors > 0 {
fmt.Printf("\nTotal errors: %d\n", s.TotalErrors)
fmt.Printf("Last error: %v\n", "")
}
fmt.Println()
fmt.Println("Type q <Enter> (or ctrl-c) to exit")
}
}
func totalIterations(iterations int, interval int, stopTime int) int64 {
var totalIterations int
if stopTime > 0 && interval > 0 {
totalIterations = ((stopTime / interval) + 1) * iterations
} else {
totalIterations = iterations
}
return int64(totalIterations)
}
func bar(n int64, total int64, size int) (bar string) {
if n == 0 {
n = 1
}
progress := int64(size) / (total / n)
return "╞" + strings.Repeat("═", int(progress)) + strings.Repeat("┄", size-int(progress)) + "╡"
}