-
Notifications
You must be signed in to change notification settings - Fork 5
/
run.go
123 lines (108 loc) · 3.61 KB
/
run.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
package main
import (
"fmt"
"github.com/mrlsd/go-benchmark-app/config"
"github.com/mrlsd/go-benchmark-app/tools"
"os/exec"
"strings"
"time"
)
// KillProcess - alias for Process.Kill()
// It's used for simplify use and testing code
var KillProcess = killProcess
// RunCommand - alias fo exec.Command.Output
// execute command and returns its standard output
var RunCommand = runCommand
// RunBenchmarks - alias for runBenchmarks
// Testing requered
var RunBenchmarks = runBenchmarks
// runBenchmarks - run all benchmarks
func runBenchmarks(config *config.Config) (tools.AggreatedResults, error) {
// Init results array
var benchResults tools.AggreatedResults
benchResults = make(tools.AggreatedResults, len(config.App))
for i := 0; i < len(config.App); i++ {
benchResults[i] = make([]tools.BenchResults, config.Try)
}
// Collect bench-tools to array
benchmarkTools := []struct {
tool tools.BenchCommand
}{
{tool: tools.AbTool{&config.Ab}},
{tool: tools.WrkTool{&config.Wrk}},
{tool: tools.SiegeTool{&config.Siege}},
}
// Repeate benchmarks
for repeat := 0; repeat < config.Try; repeat++ {
// Go through applications
for i := 0; i < len(config.App); i++ {
fmt.Printf("[%d]... %s\n", repeat+1, config.App[i].Title)
// Get app command and Run it
cmd := exec.Command(config.App[i].Path)
if err := cmd.Start(); err != nil {
return benchResults, fmt.Errorf("Failed execute:\n\t%s\n\t%s", config.App[i].Path, err.Error())
}
// Wait when app starting
time.Sleep(config.WaitToRun * time.Second)
// Go through Benchmark tools
for j := 0; j < len(benchmarkTools); j++ {
// Generate bench-command
results, err := benchmarkTools[j].tool.BenchCommand(config.App[i].Url)
if err != nil {
return benchResults, fmt.Errorf("Failed run bachmark tool:\n\t%s \n\t%v \n\t%s", results.Command(), results.Params(), err)
}
// Run specific bench-tool
printRunBenchCommand(&results)
output, err := RunCommand(results.Command(), results.Params()...)
if err != nil {
KillProcess(cmd)
println(string(output))
return benchResults, fmt.Errorf("Bachmark failed result:\n\t%s \n\t%v \n\t%s", results.Command(), results.Params(), err)
}
// Parse bench-output
parsed, err := results.Parse(output)
if err != nil {
return benchResults, err
}
// Aggregate benchmark results by:
// Application iterator, Repeat iterator, Bench-tool type
aggregateResults(&parsed, &benchResults[i][repeat])
time.Sleep(config.Delay * time.Second)
fmt.Println("\t[done]")
}
if err := KillProcess(cmd); err != nil {
return benchResults, fmt.Errorf("KillProcess error: %s", err.Error())
}
}
}
return benchResults, nil
}
// killProcess - immediately kill process
func killProcess(cmd *exec.Cmd) error {
return cmd.Process.Kill()
}
// runCommand - execute command and
// returns its output
func runCommand(command string, args ...string) ([]byte, error) {
return exec.Command(command, args...).CombinedOutput()
}
// aggregateResults - get Bench Resuls by it type
func aggregateResults(data *tools.Results, benchResults *tools.BenchResults) {
switch values := (*data).(type) {
case tools.AbResults:
benchResults.Ab = values
case tools.WrkResults:
benchResults.Wrk = values
case tools.SiegeResults:
benchResults.Siege = values
}
}
// printRunBenchCommand - print running bench-commang
func printRunBenchCommand(result *tools.Results) {
if config.Cfg.Verbose {
fmt.Printf("Run command: %s %v\n", (*result).Command(), (*result).Params())
} else {
path := strings.Split((*result).Command(), "/")
fmt.Printf(" Run command: %s", path[len(path)-1])
}
}